Home > front end >  ReactJS state does not return the right value
ReactJS state does not return the right value

Time:02-17

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.

CodePudding user response:

Welcome to StackOverflow and React.

The reason why your history array always returns [] is because of the way react works - don't worry there is a simple fix to this ;)

Inside of your App.js you have addMsg function that makes use of the messages array. Your function get's initialised with the values of the messages array on the first render and the values does not change after that.

To fix this simple change your function from this:

const addMsg = (data) => {
  return addMessage([...messages, data]); 
};

to this:

const addMsg = (data) => {
  return addMessage(history => [...history, data]); 
};

To learn more about it:

CodePudding user response:

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.

  • Related