'ReactJS state does not return the right value

Problem:

I am building a simple chat app, in App.js I am saving the message history and in Screen.js I handle the input, etc.

The problem I am facing is that when I add a new message to the history it always overwrites the complete history.

What I did:

  • I added useEffect(() => {...}, [messages]); to App.js to check if new messages are saved - and they are.
  • Then I added a console.log(messages) to the addMsg() in App.js AND in Screen.js and discovered that this console.log always returns an empty array.

I have no idea why messages returns data in the useEffect but not inside the addMsg function ...

Code:

App.js

const [messages, addMessage] = useState([]); 

# this function is passed down as a prop to add new messages to the history
const addMsg = (data) => {
  console.log('  old history', messages); 

  return addMessage([...messages, data]); 
};

...

return (
  <div className="App">
    <Screen messages={messages} addMsg={addMsg} />
  </div>
)

This is how I call the addMsg function from Screen.js:

props.addMsg(data);

Screen.js:

function Screen(props) {

  useEffect(() => {
    console.log('props.messages', props.messages); // always returns []
  }, [props.messages]);


  const sendMsg = (msg) => {

    let data = {
      timestamp: Date.now(), 
      id: props.id, 
      msg: msg, 
      key: props.messages.length+1,  
    }; 
 
    props.addMsg(data);

  }



  return (
    <div className="screen">
      <div className="messages">
        {
          props.messages.map(obj => {
            return <Row key={obj.key} id={obj.id} timestamp={obj.timestamp} msg={obj.msg} />
          })
        }
      </div>

      <Input id={props.id} send={sendMsg} />

    </div>
  )
}

Basically I just pass an object to addMsg that then get's added to the history (messages) array.

I am relatively new to React and have been stuck on this for hours ...

Clarification

It's a simple chat app. The messages array holds all messages (like a history). When I add a new message the history array get's reset but I do not know why. When I add a message it does get added to the history array (I tested this with an useEffect handler [messages]); but I also added a console.log to the addMessage function that always tells me that my history array is empty ... I have no idea why.



Solution 1:[1]

In your code addMsg returns addMessage which is a useState setter. After that the useEffect handlers get triggered and they already have the updated value.

But an useState setter doesn't return a value, so you'll have to adjust the addMsg function to return a value.

That's why you see the changed value in useEffect and not returned by addMsg

const addMsg = (data) => {
  console.log('  old history', messages); 

  let newMessages = [...messages, data];
  addMessage(newMessages); 
  // After the setter call the 'messages' variable 
  // is not yet updated, so use the 'newMessages' variable.

  return newMessages
};

Now addMsg returns the new array.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1