Search code examples
react-nativesocket.iochatflatlist

Append an element to the top of an inverted FlatList


I'm currently working on a React Native Chat App and I am trying to display the chat messages in a conventional way. I am using the Expo CLI along with Socket.io and my messages FlatList looks like following:

<FlatList
    ref={chatRef}
    data={messages}
    keyExtractor={item => item._id}
    showsVerticalScrollIndicator={false}
    renderItem={renderItem}
    onContentSizeChange={onContentSizeChange}
    onEndReachedThreshold={0.2}
    inverted
    onEndReached={loadMore}
    removeClippedSubviews={true}
/>

const onContentSizeChange = () => {
    chatRef.current.scrollToOffset({ animated: true, offset: 0 })
}

My chat is working as expected and well displayed but whenever I send a new message it's been appended at the top of the FlatList.

When a new chat is sent, I dispatch an action to my reducer and I add the message as following:

{...}
case ADD_MESSAGE: return {
    ...state,
    messages: [...state.messages, action.payload]
}
{...}

I am wondering if it is possible to append the new message at the end of the FlatList and scroll to the end of it.

Note: My messages array is order by newest to oldest

Thanks to anyone who can help me!


Solution

  • FlatList has a scrollToIndex method: https://reactnative.dev/docs/flatlist#scrolltoindex

    Without seeing more of your code, it's hard to tell how you're reacting to props changes, but assuming you're using hooks, you could do something like:

    React.useEffect(() => {
      chatRef.current.scrollToIndex({{animated: true, index: messages.length - 1}})
    },[messages])
    

    That should scroll to the last message. If you want it to scroll to the first one, go to index: 0.

    Regarding the order of your messages array, it seems like you have conflicting information; you said that it's ordered newest -> oldest, but in your action, you show [...state.messages, action.payload] which would seem to take the newest message onto the end of it. However, you can always switch the order ([action.payload,...state.messages])

    Regarding inverted as one of the parameters to your list: I haven't experimented with this, but documentation says it "Reverses the direction of scroll." May want to be careful with how this affects your perception of ordering as well.