I want to implement a functionality that would load a list objects from a REST call when the page loads the first time and then it would consume new objects from WebSocket events and update/append them correspondingly.
const [objects, setObjects] = useState([])
useEffect(() => {
axios.get(`${process.env.REACT_APP_REST_API}/objects`)
.then(resp => setObjects(resp.data))
}, [])
const ws = new WebSocket(`${process.env.REACT_APP_WS_API}/objects`)
ws.onmessage = (event) => {
const obj = JSON.parse(event.data)
const items = [...objects]
const index = items.findIndex((it) => it.id === obj.id)
if (index === -1) {
items.push(obj)
} else {
items[index] = obj
}
setObjects(items)
};
This code doesn't work. It opens WS connections several times. Also the initial data disappears from time to time and only the last object is shown. I understand, that it is related to the fact that react re-renders the component. And the issue with disappearing elements is most likely related to the scope of the closure used in the WS handler. At the same time, I have no idea how to solve it in React.
Q: How can I preload elements with a REST call and keep updating them further consuming events from WebSocket in a React component?
const [objects, setObjects] = useState([])
useEffect(() => {
axios.get(`${process.env.REACT_APP_REST_API}/objects`)
.then(resp => setObjects(resp.data));
const ws = new WebSocket(`${process.env.REACT_APP_WS_API}/objects`)
ws.onmessage = (event) => {
const obj = JSON.parse(event.data)
const index = objects.findIndex((it) => it.id === obj.id)
if (index === -1) {
setObjects((current)=>[...current, obj]);
} else {
items[index] = obj
setObjects((current)=> current[index]= obj);
}
};
return () => { ws.close(); }
}, [])