最完整的 React Native 和 Web 聊天 UI
演示网?
小吃 GiftedChat 游乐场
巴黎编码训练营由 Farid Safi 共同创立
点击了解更多
用 Go 编写的可扩展聊天 API/服务器
API 之旅 | React Native 天才教程
具有 GiftedChat 功能的完整应用程序引擎
查看我们的 GitHub
react-native-web
能够(自 0.10.0 起) Web 配置纱:
yarn add react-native-gifted-chat react-native-reanimated react-native-safe-area-context react-native-get-random-values
国家PM:
npm install --save react-native-gifted-chat react-native-reanimated react-native-safe-area-context react-native-get-random-values
世博会
npx expo install react-native-gifted-chat react-native-reanimated react-native-safe-area-context react-native-get-random-values
npx pod-install
遵循指南:react-native-safe-area-context
遵循指南:react-native-reanimated
0.11.0
开始,这两个依赖项都被删除。video
,但需要提供renderMessageVideo
属性。 TEST_ID
导出为常量,可在您选择的测试库中使用
Gifted Chat 使用onLayout
来确定聊天容器的高度。要在测试期间触发onLayout
,您可以运行以下代码。
const WIDTH = 200 ; // or any number
const HEIGHT = 2000 ; // or any number
const loadingWrapper = getByTestId ( TEST_ID . LOADING_WRAPPER )
fireEvent ( loadingWrapper , 'layout' , {
nativeEvent : {
layout : {
width : WIDTH ,
height : HEIGHT ,
} ,
} ,
} )
import React , { useState , useCallback , useEffect } from 'react'
import { GiftedChat } from 'react-native-gifted-chat'
export function Example ( ) {
const [ messages , setMessages ] = useState ( [ ] )
useEffect ( ( ) => {
setMessages ( [
{
_id : 1 ,
text : 'Hello developer' ,
createdAt : new Date ( ) ,
user : {
_id : 2 ,
name : 'React Native' ,
avatar : 'https://placeimg.com/140/140/any' ,
} ,
} ,
] )
} , [ ] )
const onSend = useCallback ( ( messages = [ ] ) => {
setMessages ( previousMessages =>
GiftedChat . append ( previousMessages , messages ) ,
)
} , [ ] )
return (
< GiftedChat
messages = { messages }
onSend = { messages => onSend ( messages ) }
user = { {
_id : 1 ,
} }
/>
)
}
请参阅App.tsx
以获取工作演示!
请参阅example/example-slack-message
中的文件,获取有关如何覆盖默认 UI 以使内容看起来更像 Slack 的示例 - 显示用户名并将所有消息显示在左侧。
例如聊天消息
export interface IMessage {
_id : string | number
text : string
createdAt : Date | number
user : User
image ?: string
video ?: string
audio ?: string
system ?: boolean
sent ?: boolean
received ?: boolean
pending ?: boolean
quickReplies ?: QuickReplies
}
{
_id : 1 ,
text : 'My message' ,
createdAt : new Date ( Date . UTC ( 2016 , 5 , 11 , 17 , 20 , 0 ) ) ,
user : {
_id : 2 ,
name : 'React Native' ,
avatar : 'https://facebook.github.io/react/img/logo_og.png' ,
} ,
image : 'https://facebook.github.io/react/img/logo_og.png' ,
// You can also add a video prop:
video : 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4' ,
// Mark the message as sent, using one tick
sent : true ,
// Mark the message as received, using two tick
received : true ,
// Mark the message as pending with a clock loader
pending : true ,
// Any additional custom parameters are passed through
}
例如系统消息
{
_id : 1 ,
text : 'This is a system message' ,
createdAt : new Date ( Date . UTC ( 2016 , 5 , 11 , 17 , 20 , 0 ) ) ,
system : true ,
// Any additional custom parameters are passed through
}
例如带有快速回复选项的聊天消息
请参阅 PR #1211
interface Reply {
title : string
value : string
messageId ?: number | string
}
interface QuickReplies {
type : 'radio' | 'checkbox'
values : Reply [ ]
keepIt ?: boolean
}
{
_id : 1 ,
text : 'This is a quick reply. Do you love Gifted Chat? (radio) KEEP IT' ,
createdAt : new Date ( ) ,
quickReplies : {
type : 'radio' , // or 'checkbox',
keepIt : true ,
values : [
{
title : '? Yes' ,
value : 'yes' ,
} ,
{
title : '? Yes, let me show you with a picture!' ,
value : 'yes_picture' ,
} ,
{
title : '? Nope. What?' ,
value : 'no' ,
} ,
] ,
} ,
user : {
_id : 2 ,
name : 'React Native' ,
} ,
} ,
{
_id : 2 ,
text : 'This is a quick reply. Do you love Gifted Chat? (checkbox)' ,
createdAt : new Date ( ) ,
quickReplies : {
type : 'checkbox' , // or 'radio',
values : [
{
title : 'Yes' ,
value : 'yes' ,
} ,
{
title : 'Yes, let me show you with a picture!' ,
value : 'yes_picture' ,
} ,
{
title : 'Nope. What?' ,
value : 'no' ,
} ,
] ,
} ,
user : {
_id : 2 ,
name : 'React Native' ,
} ,
}
messageContainerRef
(FlatList ref) - 引用平面列表textInputRef
(TextInput ref) - 文本输入的引用messages
(Array) - 要显示的消息isTyping
(Bool) - 打字指示器状态;默认false
。如果你使用renderFooter
它将覆盖它。text
(字符串) - 输入文本;默认为undefined
,但如果指定,它将覆盖 GiftedChat 的内部状态(例如,对于 redux;请参阅下面的注释)placeholder
(String) - text
为空时的占位符;默认为'Type a message...'
messageIdGenerator
(函数) - 为新消息生成 ID。默认为UUID v4,由uuid生成user
(Object) - 发送消息的用户: { _id, name, avatar }
onSend
(Function) - 发送消息时回调alwaysShowSend
(Bool) - 始终在输入文本编辑器中显示发送按钮;默认false
,仅当文本输入不为空时显示locale
(String) - 用于本地化日期的区域设置。您首先需要导入所需的语言环境(即require('dayjs/locale/de')
或import 'dayjs/locale/fr'
)timeFormat
(String) - 用于渲染时间的格式;默认为'LT'
(请参阅 Day.js 格式)dateFormat
(String) - 用于渲染日期的格式;默认为'll'
(请参阅 Day.js 格式)loadEarlier
(Bool) - 启用“加载较早消息”按钮,这是infiniteScroll
所必需的onLoadEarlier
(Function) - 加载较早消息时的回调isLoadingEarlier
(Bool) - 加载早期消息时显示ActivityIndicator
renderLoading
(函数) - 初始化时渲染加载视图renderLoadEarlier
(函数) - 自定义“加载早期消息”按钮renderAvatar
(Function) - 自定义消息头像;设置为null
以不呈现消息的任何头像showUserAvatar
(Bool) - 是否为当前用户渲染头像;默认为false
,仅显示其他用户的头像showAvatarForEveryMessage
(Bool) - 当为 false 时,仅当同一天来自同一用户的连续消息时才会显示头像;默认为false
onPressAvatar
(Function( user
)) - 点击消息头像时的回调onLongPressAvatar
(Function( user
)) - 长按消息头像时的回调renderAvatarOnTop
(Bool) - 在连续消息的顶部而不是底部渲染消息头像;默认为false
renderBubble
(函数) - 自定义消息气泡renderTicks
(Function( message
)) - 自定义刻度指示器以显示消息状态renderSystemMessage
(Function) - 自定义系统消息onPress
(Function( context
, message
)) - 按下消息气泡时的回调onLongPress
(Function( context
, message
)) - 长按消息气泡时的回调(请参阅使用showActionSheetWithOptions()
的示例)inverted
(Bool) - 反转messages
的显示顺序;默认为true
renderUsernameOnMessage
(Bool) - 指示是否在消息气泡内显示用户的用户名;默认为false
renderUsername
(函数) - 自定义用户名容器renderMessage
(函数) - 自定义消息容器renderMessageText
(函数) - 自定义消息文本renderMessageImage
(函数) - 自定义消息图像renderMessageVideo
(Function) - 自定义消息视频imageProps
(Object) - 要传递给默认renderMessageImage
创建的<Image>
组件的额外道具videoProps
(Object) - 要传递给由所需renderMessageVideo
创建的视频组件的额外道具lightboxProps
(Object) - 要传递到MessageImage
的 Lightbox 的额外道具isCustomViewBottom
(Bool) - 确定 renderCustomView 是显示在文本、图像和视频视图之前还是之后;默认为false
renderCustomView
(Function) - 气泡内的自定义视图renderDay
(函数) - 消息上方的自定义日期renderTime
(函数) - 消息内的自定义时间renderFooter
(Function) - ListView 上的自定义页脚组件,例如'User is typing...'
;有关示例,请参阅 App.tsx。覆盖当isTyping
为 true 时触发的默认键入指示器。renderChatEmpty
(函数) - 当消息为空时在 ListView 中呈现的自定义组件renderChatFooter
(函数) - 在 MessageContainer 下方呈现的自定义组件(与 ListView 分开)renderInputToolbar
(函数) - 自定义消息编辑器容器renderComposer
(Function) - 自定义文本输入消息编辑器renderActions
(Function) - 消息编辑器左侧的自定义操作按钮renderSend
(Function) - 自定义发送按钮;您可以很容易地将子项传递给原始Send
组件,例如,使用自定义图标(示例)renderAccessory
(Function) - 消息编辑器下方的自定义第二行操作onPressActionButton
(Function) - 按下 Action 按钮时的回调(如果设置,将不会使用默认的actionSheet
)bottomOffset
(整数) - 聊天距屏幕底部的距离(例如,如果您显示选项卡栏,则很有用)minInputToolbarHeight
(Integer) - 输入工具栏的最小高度;默认为44
listViewProps
(Object) - 要传递给消息<ListView>
额外道具;有些道具无法被覆盖,请参阅MessageContainer.render()
中的代码了解详细信息textInputProps
(Object) - 要传递给<TextInput>
的额外道具textInputStyle
(Object) - 要传递给<TextInput>
的自定义样式multiline
(Bool) - 指示是否允许<TextInput>
为多行;默认true
。keyboardShouldPersistTaps
(Enum) - 确定键盘在点击后是否应保持可见;请参阅<ScrollView>
文档onInputTextChanged
(Function) - 输入文本改变时回调maxInputLength
(整数) - 最大消息编辑器文本输入长度parsePatterns
(Function) - 用于链接消息内容(如 URL 和电话号码)的react-native-parsed-text 的自定义解析模式,例如: < GiftedChat
parsePatterns = { ( linkStyle ) => [
{ type : 'phone' , style : linkStyle , onPress : this . onPressPhoneNumber } ,
{ pattern : / #(w+) / , style : { ... linkStyle , styles . hashtag } , onPress : this . onPressHashtag } ,
] }
/>
extraData
(Object) - 用于根据需要重新渲染 FlatList 的额外道具。这对于渲染页脚等很有用。minComposerHeight
(对象) - 作曲家的自定义最小高度。maxComposerHeight
(对象) - 编辑器的自定义最大高度。scrollToBottom
(Bool) - 启用滚动到底部组件(默认为 false)scrollToBottomComponent
(函数) - 自定义滚动到底部组件容器scrollToBottomOffset
(整数) - 开始显示滚动到底部组件的自定义高度偏移(默认值为 200)scrollToBottomStyle
(Object) - 底部组件容器的自定义样式alignTop
(布尔值)控制消息气泡是否出现在聊天的顶部(默认为 false - 气泡与底部对齐)onQuickReply
(Function) - 发送快速回复时的回调(到后端服务器)renderQuickReplies
(Function) - 自定义所有快速回复视图quickReplyStyle
(StyleProp) - 自定义快速回复视图样式renderQuickReplySend
(Function) - 自定义快速回复发送视图shouldUpdateMessage
(函数) - 让消息组件知道何时在正常情况之外进行更新。infiniteScroll
(Bool) - 当到达消息容器顶部时无限向上滚动,如果存在则自动调用 onLoadEarlier 函数(Web 尚不支持)。您还需要添加loadEarlier
属性。isStatusBarTranslucentAndroid
(Bool) - 如果您在 Android 上使用半透明状态栏,请将此选项设置为 true。在 iOS 上被忽略。 messages
属性应该可以与 Redux 一起开箱即用。在大多数情况下,这就是您所需要的。
如果您决定指定text
道具,GiftedChat 将不再管理其自己的内部text
状态,并将完全遵循您的道具。这对于使用像 Redux 这样的工具来说非常有用,但是您需要采取一个额外的步骤:只需实现onInputTextChanged
来接收打字事件和重置事件(例如清除onSend
文本):
< GiftedChat
text = { customText }
onInputTextChanged = { text => this . setCustomText ( text ) }
/* ... */
/>
如果您使用 Create React Native App / Expo,则不需要 Android 特定的安装步骤 - 您可以跳过本节。否则,我们建议按如下方式修改您的项目配置。
确保AndroidManifest.xml
中有android:windowSoftInputMode="adjustResize"
:
< activity
android : name = " .MainActivity "
android : label = " @string/app_name "
android : windowSoftInputMode = " adjustResize "
android : configChanges = " keyboard|keyboardHidden|orientation|screenSize " >
对于Expo来说,至少有 2 个解决方案可以修复它:
KeyboardAvoidingView
。这应该只适用于 Android,因为KeyboardAvoidingView
可能与 GiftedChat 中内置的 iOS 键盘避免冲突,例如: <View style={{ flex: 1 }}>
<GiftedChat />
{
Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />
}
</View>
如果您使用 React Navigation,可能需要额外的处理来考虑导航标题和选项卡。 KeyboardAvoidingView
的keyboardVerticalOffset
属性可以设置为导航标题的高度,并且可以设置tabBarOptions.keyboardHidesTabBar
以防止键盘弹起时显示选项卡栏。由于在带有凹口的 Android 手机上计算高度时存在错误,因此建议使用KeyboardAvoidingView
而不是涉及计算窗口高度的其他解决方案。
在 app.json 上添加不透明的背景状态栏(即使在 Expo 的 Android 应用程序内部设置了android:windowSoftInputMode="adjustResize"
,半透明的状态栏会导致其无法工作):https://docs.expo.io/versions /latest/guides/configuration.html#androidstatusbar
如果您打算在Modal
中使用GiftedChat
,请参阅#200。
yarn global add expo-cli
yarn install
expo start
yarn global add expo-cli
yarn install
expo start -w
升级零食版
yarn add -D react-app-rewired
touch config-overrides.js
module . exports = function override ( config , env ) {
config . module . rules . push ( {
test : / .js$ / ,
exclude : / node_modules[/\](?!react-native-gifted-chat|react-native-lightbox|react-native-parsed-text) / ,
use : {
loader : 'babel-loader' ,
options : {
babelrc : false ,
configFile : false ,
presets : [
[ '@babel/preset-env' , { useBuiltIns : 'usage' } ] ,
'@babel/preset-react' ,
] ,
plugins : [ '@babel/plugin-proposal-class-properties' ] ,
} ,
} ,
} )
return config
}
您可以在这里找到示例和网络演示:xcarpentier/gifted-chat-web-demo
盖茨比的另一个例子:xcarpentier/clean-archi-boilerplate
请随时在 Twitter @FaridSafi 上向我提问!或@xcapetir!
正在寻找拥有超过 14 年经验的 ReactNative 自由专家?从泽维尔的网站联系他!