i am using react native and creating a chat app. Now i have few messages objects in array and i’m rendering them in flatlist now when i type message and click on send. my typed message gets clear after adding the message in array of messages. but message does not add on screen with rest of messages. as it seems like component is not rerendering cause when i click on send , message disappear from string but in array of list there that message added succesfully with rest of messages
Now, Can you please tell me whats wrong here in code ?
const ChatComponent = (props) => {
const [message, setMessage] = useState('');
const [messages, setMessages] = useState([
{ id: '1', text: 'Hello, how are you?', sender: 'John' },
{ id: '2', text: 'Im good, thanks for asking!', sender: 'Jane' },
{ id: '3', text: 'What have you been up to?', sender: 'John' },
{ id: '4', text: 'Not much, just working and taking care of some errands.', sender: 'Jane' },
]);
const listRef = useRef(null);
useEffect(() => {
setMessages(messages);
}, [messages]);
const handleSend = () => {
LayoutAnimation.configureNext({
duration: 500,
update: {
type: LayoutAnimation.Types.easeInEaseOut,
},
}, () => {
setMessages([...messages, { id: messages.length + 1, text: message, sender: 'Me' }]);
setMessage('');
});
};
return (
<SafeAreaView style={styles.container}>
<FlatList
ref={listRef}
data={messages}
renderItem={({ item }) => (
<View style={[styles.messageContainer, item.sender === 'Me' && styles.me]}>
<Text style={[styles.sender, item.sender === 'Me' && styles.me]}>{item.sender}:</Text>
<Text style={[styles.message, item.sender === 'Me' && styles.me]}>{item.text}</Text>
</View>
)}
keyExtractor={item => item.id}
/>
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
placeholder="Type a message..."
value={message}
onChangeText={text => setMessage(text)}
/>
<TouchableOpacity style={styles.button} onPress={handleSend}>
<Text style={styles.buttonText}>Send</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
};
3
Answers
remove the useEffect.
It will re-render the component infinitely since you are setting the same useState included in the dependency array
You need to remove this setFunction
setMessage('');
because react uses queue, that mean the messages state will get the last state value.Updating code inside the LayoutAnimation callback not synchronize with React UI rendering.
Remove layout animation code inside button press event handler and delegate it to useEffect as below :
You will both maintain layout animation and state updates.
Working Demo – https://snack.expo.dev/@emmbyiringiro/ea7d26