Mint
Mint

Reputation: 1059

Why is my state empty when updating on socket event?

I have a chat component that connects to a socket and retrieves messages. On the event allMessages I set the messages to the state via setMessages, works as expected. My issue is when the event newMessage is called it seems messages is empty. How can I add the new message to the list of current messages?

export default function ChatPage(props) {
  
  const {socket} = useSelector((state) => state.socket);
  const [messages, setMessages] = useState([]);
  const [message, setMessage] = useState('');
  const [chatId, setChatId] = useState(null);
  const classes = useStyles();

  function handleSubmit(event) {
    event.preventDefault();
    if (socket && chatId) {
      socket.emit('submitNewMessage', ({content: message, chatId: chatId}));
      setMessage('');
    };
  };

  useEffect(async () => {
    let res = await api.getChatId({friendId: props.match.params.userId});
    if (res.status === 200 && res.data.chatId) {
      setChatId(res.data.chatId);
    };
  },[]);

  useEffect(() => {
    if (chatId && socket) {
      socket.emit('joinChat', chatId);
      socket.on('allMessages', (allMessages) => {
        setMessages([...allMessages]);
      });
      socket.on('newMessage', (newMessage) => {
        setMessages([...messages, newMessage])
      });
    };
  }, [chatId, socket]);

  return (
    <Grid container className={classes.root}>
    <Navbar />
    <main className={classes.main}>
      <Grid>
            <Typography variant='h4'>
              Chat Page {props.match.params.userId}
            </Typography>
        {messages && messages.map(message => (
          <Typography variant='h4'>
            {message.content}
              </Typography>))
        }
        <Grid item>
          <TextField
                id="input"
            name="message"
            value={message}
            onChange={(event)=> setMessage(event.target.value)}
                label="Multiline"
                multiline
                rows={4}
                defaultValue="Default Value"
                variant="outlined"
              />
          <Button type="submit" onClick={handleSubmit}>Submit</Button>
        </Grid>
      </Grid>
          
    </main>
   </Grid>
  );
};

Upvotes: 0

Views: 382

Answers (1)

gunwin
gunwin

Reputation: 4832

This seems to be a scoping issue. Pass a function into setMessages instead:

 setMessages(msgs => [...msgs, newMessage])

The msgs argument will give you access to the current value, and the return value is the new state you wish to be set.

Upvotes: 1

Related Questions