Skip to content
Advertisement

Component is not rerendering even i used useeffect and state is changing?

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>
  );
};

Advertisement

Answer

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 :

 useEffect(()=>{
      LayoutAnimation.configureNext({
        duration: 500,
        update: {
          type: LayoutAnimation.Types.easeInEaseOut,
        },
      });

  },[messages.length])

  const handleSend = () => {
      setMessages([...messages, { id: messages.length + 1, text: message, sender: 'Me' }]);
      setMessage('');
  };

You will both maintain layout animation and state updates.

Working Demo – https://snack.expo.dev/@emmbyiringiro/ea7d26

Advertisement