Reputation: 109
I'm building chat app using ReactJS, NestJS, Socket.io .
And it's multi channel using rooms in socket.io
const [messages, setMessages] = useState({
ReactJS: [],
NestJS: [],
Typescript: [],
MySQL: [],
Neo4j: [],
Redis: [],
ELK: [],
Docker: [],
Kubernetes: [],
AWS: [],
SocketIO: [],
});
This is array with useState for pushing message.
messages['ReactJS'].push(someMessage);
How useState push element to array inside object?
Upvotes: 1
Views: 1884
Reputation: 2341
If you can install some additional utilities here are some other way to do it
rootPath = 'ReactJS'
const newArray = R.append(someMessage, messages[rootPath])
const newMessages = R.assocPath([rootPath], newArray, messages);
setMessages(newMessages)
// combined
const rootPath = 'ReactJS'
setMessages(
R.assocPath(
[rootPath],
R.append(
someMessage,
messages[rootPath]
),
messages
)
)
import produce from 'immer'
const rootPath = 'ReactJS'
const newMessages = produce(messages, draftState => {
draftState[rootPath].push = someMessage
})
setMessages(newMessages)
// combined
import p from 'immer'
const rootPath = 'ReactJS'
setMessages(p(messages, draft => {
draft[rootPath].push = someMessage
}))
Upvotes: 0
Reputation: 202608
Given the state
const [messages, setMessages] = useState({
ReactJS: [],
NestJS: [],
Typescript: [],
MySQL: [],
Neo4j: [],
Redis: [],
ELK: [],
Docker: [],
Kubernetes: [],
AWS: [],
SocketIO: [],
});
Then the following is a way to update a specific room via a roomKey
identifier nested in the state object. In React when you update state you must always return a new object reference, and this includes any nested state/properties that are being updated. array.prototype.push mutates the original array, it doesn't create a new array reference for React purposes.
setMessages(messages => ({
...messages, // <-- shallow copy state
// copy existing nested state array into new array and append new element
[roomKey]: [...messages[roomKey], newMessage],
}));
An alternative to the array literal is to use array.prototype.concat, which does return a new array.
setMessages(messages => ({
...messages, // <-- shallow copy state
// copy existing nested state array into new array and append new element
[roomKey]: messages[roomKey].concat(newMessage),
}));
Note: This assumes your roomKey
variable will reference one of the keys actually defined in your state. If you use an unspecified key then messages[unknownKey]
will be undefined. In this case, if you've truly dynamic keys, then you can provide a fallback value to spread into state.
setMessages(messages => ({
...messages, // <-- shallow copy state
// copy existing nested state array into new array and append new element
[roomKey]: [
...messages[roomKey] || [], // <-- provide fallback
newMessage,
],
}));
Upvotes: 3