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 theaddMsg()
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.