1

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.

1 Answers1

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.

Casper Kuethe
  • 1,070
  • 8
  • 13
  • Nothing is done with the returned value from addMsg, how does this help? – Will Jenkins Feb 16 '22 at 14:58
  • The question was why addMsg doesn't return any data. I've ansewered the question. What he wants to do with it is his choice – Casper Kuethe Feb 16 '22 at 14:59
  • where does it say that? – Will Jenkins Feb 16 '22 at 15:01
  • I see `The problem I am facing is that when I add a new message to the history it always overwrites the complete history.` and `I have no idea why messages returns data in the useEffect but not inside the addMsg function ...` - nothing about returning *from* a function – Will Jenkins Feb 16 '22 at 15:02
  • I've updated my answer to more clarify it. My bad read it wrong – Casper Kuethe Feb 16 '22 at 15:02
  • it doesn't make any sense, no-where in the code are they reading any value returned from `addMsg`. The question is worded confusingly, but I don't think your answer fits any of the possible interpretations. – Will Jenkins Feb 16 '22 at 15:04
  • Yes, i am sorry for the confusion. I am new to react and if I would do the same in vanilla JS this would be solved in seconds .. but I am learning states now :) –  Feb 16 '22 at 15:09
  • no, this answer doesn't make any sense - your question at least makes *some* sense :-) – Will Jenkins Feb 16 '22 at 15:10