React Native Gifted Chat

repository·master·Indexed 12 days ago

https://github.com/faridsafi/react-native-gifted-chat

A highly customizable and feature-rich chat UI library for React Native and Web, version 3.4.1. It supports advanced features such as message threading, emoji reactions, quick replies, and smart link parsing. The library provides extensive render props for customizing components like the input toolbar, message bubbles, and avatars. Note: This package is currently in maintenance mode.

Tokens
22.1K
Snippets
55
Records
84
Agent score
96%

What's inside React Native Gifted Chat

  1. How the Telegram-style sticky day header works

    master

    The library implements a Telegram-style sticky day header using two distinct elements that work together to create a seamless transition:

    1. Inline Separator: A date pill rendered within the message list (Item component) that scrolls normally with the content.
    2. Floating Header: A sticky overlay (DayAnimated) that pins the date of the topmost visible day just below the navigation bar during active scrolling.

    Key Behaviors

    • Scroll-Gated Visibility: The header is hidden when the list is at rest. It fades in quickly when scrolling starts (including momentum) and fades out after motion stops.
    • Slide Transition: When crossing a day boundary, the dates do not cross-fade. Instead, the new date slides into position (down from the top when scrolling up, or up from the bottom when scrolling down) while the previous date is pushed out.
    • Handoff Logic: To prevent duplicate dates or flickering, the library uses a 'hard cutoff' handoff. The inline separator hides exactly when the floating header takes over at a specific pixel offset (DAY_HANDOFF_OFFSET).
    • Top of History: When scrolling to the very top (e.g., triggering 'Load earlier'), the floating header hides to avoid overlapping with the loading indicator.
    /* Conceptual Model Summary */
    // 1. Inline Separator: Scrolls with content
    // 2. Floating Header: Sticks to top during scroll
    // Transition: Sliding (not fading) between dates
    // Visibility: Only visible during active scroll/momentum
  2. Enable Emoji Reactions

    master

    Emoji reactions allow users to react to messages with a quick picker. Reaction state (the reactions array on the message object) is managed by the developer.

    Configuration

    • reactions.isEnabled: Enables the feature.
    • reactions.emojis: Array of emojis for the quick picker.
    • reactions.onReactionPress: Callback (message, emoji) => void. You must implement the logic to add/remove reactions from your message data.
    • reactions.renderReactionPicker: Optional override for a custom emoji browser.
    interface IChatMessage extends IMessage {
      reactions?: { emoji: string, userIds: (string | number)[] }[]
    }
    
    // In your component:
    <GiftedChat
      messages={messages}
      onSend={onSend}
      user={{ _id: CURRENT_USER_ID }}
      reactions={{
        isEnabled: true,
        onReactionPress: handleReactionPress,
      }}
    />
  3. Implement Swipe-to-Reply

    master

    GiftedChat supports swipe-to-reply using react-native-reanimated and react-native-gesture-handler. You must manage the replyMessage state externally to enable controlled replies.

    Configuration

    • reply.swipe.isEnabled: Enables the gesture.
    • reply.swipe.direction: 'left' or 'right'.
    • reply.swipe.onSwipe: Callback that receives the swiped message.
    • reply.message: The currently active reply message object.
    • reply.onClear: Callback when the reply is cleared.
    const [replyMessage, setReplyMessage] = useState<ReplyMessage | null>(null)
    
    <GiftedChat
      messages={messages}
      onSend={messages => {
        const newMessages = messages.map(msg => ({
          ...msg,
          replyMessage: replyMessage || undefined,
        }))
        setMessages(prev => GiftedChat.append(prev, newMessages))
        setReplyMessage(null)
      }}
      user={{ _id: 1 }}
      reply={{
        swipe: {
          isEnabled: true,
          direction: 'right',
          onSwipe: setReplyMessage,
        },
        message: replyMessage,
        onClear: () => setReplyMessage(null),
      }}
    />
  4. Understanding the DayAnimated Render Gate

    master

    Because the header's date text is updated via runOnJS (React state), there is a potential ~1 frame lag between the UI animation (running on the worklet/UI thread) and the text update (running on the JS thread). This can cause a 'wrong date flash' when scrolling into a newer day.

    To prevent this, the library uses a Render Gate mechanism:

    1. DayAnimated tracks the createdAt value it is actually rendering via a useEffect and a shared value called floatingRenderedDate.
    2. The header's visibility is multiplied by a renderGate factor: renderGate = sticky.createdAt === floatingRenderedDate ? 1 : 0.
    3. If the text hasn't caught up to the current sticky day, the header is hidden, and the inline separator (which is already correct) remains visible to cover the gap.

    Result: The header opacity is calculated as: fade * stuckGate * renderGate.

  5. Setup and run the example project

    master

    To run the provided example application, follow these steps to install dependencies for both the root repository and the example directory, then build and start the app.

    1. Install root dependencies and example dependencies:

      yarn install
      cd example
      yarn install
    2. Install the native development build (required once or after native dependency changes):

      • For iOS: yarn installDevBuild:ios
      • For Android: yarn installDevBuild:android
    3. Start the application on the iOS simulator:

      yarn start:ios
    yarn install
    cd example
    yarn install
    yarn installDevBuild:ios
    yarn start:ios
  6. Run the Gifted Chat example app

    master

    A comprehensive example app is available in the example directory of the repository. It demonstrates features like custom bubbles, avatars, replies, quick replies, typing indicators, and attachments.

    To run the example locally:

    # Clone and install
    git clone https://github.com/FaridSafi/react-native-gifted-chat.git
    cd react-native-gifted-chat/example
    yarn install
    
    # Run on iOS
    npx expo run:ios
    
    # Run on Android
    npx expo run:android
    
    # Run on Web
    npx expo start --web
    git clone https://github.com/FaridSafi/react-native-gifted-chat.git
    cd react-native-gifted-chat/example
    yarn install
    
    npx expo run:ios
    npx expo run:android
    npx expo start --web
  7. Customizing components with Render Props in Gifted Chat

    master

    To customize the appearance of specific components while maintaining their core functionality, react-native-gifted-chat provides a variety of renderProps.

    Warning: When overriding components like renderSend, you may lose built-in behaviors (such as the automatic clearing of the input text after a message is sent) if you do not manually implement that logic within your custom component. To avoid this, ensure your custom component correctly handles the internal state and callbacks provided by the library.

    // Example of the types of render props available for customization:
    <GiftedChat
      renderInputToolbar={...}
      renderActions={...}
      renderComposer={...}
      renderSend={...}
      renderAvatar={...}
      renderBubble={...}
      renderSystemMessage={...}
      renderMessage={...}
      renderMessageText={...}
      renderCustomView={...}
    />
  8. Configure Android keyboard behavior

    master

    To prevent the TextInput from being hidden by the keyboard on Android, ensure your AndroidManifest.xml is configured with android:windowSoftInputMode="adjustResize" within the <activity> tag.

    If you are using Expo, you may need to append a KeyboardAvoidingView after the GiftedChat component to handle layout correctly on Android:

    <View style={{ flex: 1 }}>
       <GiftedChat />
       {Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" />}
    </View>
    <activity
      android:name=".MainActivity"
      android:label="@string/app_name"
      android:windowSoftInputMode="adjustResize"
      android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
  9. Install react-native-gifted-chat in Bare React Native projects

    master

    For bare React Native projects, follow these three steps:

    Step 1: Install packages Using yarn:

    yarn add react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller

    Using npm:

    npm install --save react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller

    Step 2: Install iOS pods

    npx pod-install

    Step 3: Configure react-native-reanimated Add the react-native-reanimated/plugin to your babel.config.js as per the official reanimated installation guide.

  10. Install react-native-gifted-chat in Expo projects

    master

    To install react-native-gifted-chat in an Expo project, use the following command to ensure all necessary peer dependencies (like reanimated and gesture handler) are installed with compatible versions:

    npx expo install react-native-gifted-chat react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-keyboard-controller