Reputation: 527
I'm building a react app with recoiljs as my state manager and I need to fetch data from a web socket and update the state accordingly. The reason I'm not using a regular array is that I need to share state across my components.
To elaborate, the component has a WebSocket connection and will have data streaming into it. It then needs to update an array by pushing the received data. The problem is due to the component lifecycle or something, the state gets written incorrectly and this is what I think happens
The problem is when response 2 comes in and setState is called, it has an old version of the state that doesn't include Response 1.
I can't seem to figure out how to fix this. Here is the stripped-down code.
import {atom} from "recoil"
import {useRecoilState} from "recoil"
const WebSocket = require("isomorphic-ws");
const statusAtom = atom<string[]>({
key: "statusAtom",
default: []
});
function Component() {
const [status, setStatus] = useRecoilState(statusAtom);
const functionCalledAfterButtonPress = () => {
ws.onmessage = function incoming(res: any) {
console.log(res.data); // for debugging
setStatus([...status, res.data]);
};
}
}
Note that I am not including things other events like ws.onopen
and return statements or whatnot and that the atom declaration and component declaration are in different files.
Upvotes: 2
Views: 1653
Reputation: 527
As Jayce444 said, the way to solve this is instead of using setStatus
with an already computed value, [...status, res.data]
, I should instead pass in a lambda statement that is called when the state is updated.
Instead of:
setStatus([..status, res.data])
Use: setStatus(prevStatus => [...prevStatus, res.data])
Upvotes: 4