Skip to content

Why does .map function return nothing in react

i have a simple react demo where to show websocket messages, but the .map function inside return statements returns nothing. No errors and no messages. Can anyone explain where the problem is in here?

const [messages, setMessages] = React.useState([])

//push the websocket messages response to const messages
const addMessage = (message) => {
    let n = messages;
    let d = message;
    n.push(d);
    setMessages(n)

    //the following both works as expected
    messages.map((item) => {
        console.log('message', item.message)
    })
    messages.map((message, index) =>
        console.log(message,index)
    )
}

Now the problem in return statement: Here was nothing returned.

 return (
   <div>
     {
       messages.map(function(message, index){
         return (<p id={'t'+index}>{message.message}</p>)
       }),

       messages.map((message, index) =>{
         return (<p id={'z'+index}>{message.message}</p>)
       })
     }
  </div>
)

Maybe the return statement is not rerendered after receiving websocket message? I hope anyone have an idea and can explain the problem.

Answer

Issue

You are mutating the messages state array by pushing directly into it and saving it back into state. The messages array reference never changes! React uses shallow object reference equality to help determine when the DOM should be updated. If the reference never updates then React bails on rerendering.

const [messages, setMessages] = React.useState([])

//push the websocket messages response to const messages
const addMessage = (message) => {
  let n = messages; // <-- reference to state
  let d = message;
  n.push(d);        // <-- state mutation
  setMessages(n).   // <-- saved back into state

  ...
}

Solution

Always shallow copy state that is being updated. Use a functional state update to update from the previous state

const [messages, setMessages] = React.useState([])

//push the websocket messages response to const messages
const addMessage = (message) => {
  setMessages(messages => [
    ...messages, // <-- shallow copy messages array
    message,     // <-- and append new message
  ])

  ...
}