Reputation: 113
I'm creating web application that receive WebSocket message and log these messages, using React, Next.js.
I have a problem with state. When I reference state, always return initial value.
my code looks like this:
import React, { useState, useEffect } from 'react';
import { Container, Row, Col } from 'react-bootstrap';
export default function Home() {
let socket = null;
const [eventLog, setEventLog] = useState([]);
const [updateFlag, setUpdateFlag] = useState(0);
const onWebSocketMessage = (e) => {
const data = JSON.parse(e.data);
setEventLog(
[
{
title: data.title,
icon: data.icon,
body: data.body,
date: new Date(),
},
].concat(eventLog)
);
setUpdateFlag(updateFlag + 1);
console.log(updateFlag);
};
const connectWebSocket = (token) => {
socket = new WebSocket('wss://localhost/' + token);
socket.onmessage = onWebSocketMessage;
};
useEffect(() => {
const token = localStorage.getItem('token');
connectWebSocket(token);
}, []);
const eventLogHtml = eventLog.map((obj, index) => (
<div key={index}>
<h2>{obj.title}</h2>
<div>
<img src={obj.icon} style={{ width: '8rem' }} />
<span>
<p>{obj.body}</p>
<p>{obj.date.toString()}</p>
</span>
</div>
</div>
));
return (
<>
<Container>
<Row>
<Col>
<h1>Event log</h1>
{eventLogHtml}
</Col>
</Row>
</Container>
</>
);
}
in this code, eventLog
always returns initial value that is []
.
And console.log(updateFlag);
always logs 0.
I expected that eventLog
and console.log(updateFlag);
increase when receive message, but actually is set only newest one and logs 0.
Any advice would be much appreciated. Thank you!
Upvotes: 1
Views: 2245
Reputation: 7044
Cause you are for got add dependencies
on useEffect
. Try this
useEffect(() => {
const token = localStorage.getItem('token');
connectWebSocket(token);
}, [eventLog]);
As Dennis said. It reconnect websocket when eventLog
change. So you must split connect and listener event.
const token = localStorage.getItem("token");
socket = new WebSocket("wss://localhost/" + token);
//outside function component
useEffect(() => {
const onMessage = () => {// do stuff}
socket.on('message', onMessage)
return () => socket.off('message', onMessage)
}, [eventLog, updateFlag])
Upvotes: 0
Reputation: 53874
You have few problems like:
updateFlag
value which won't rerender on the next messagesocket
and connection functionssetState
is async.To summarize check fixed code:
let socket = null;
export default function Home() {
const [eventLog, setEventLog] = useState([]);
const [updateFlag, setUpdateFlag] = useState(0);
useEffect(() => {
console.log(updateFlag);
}, [updateFlag]);
useEffect(() => {
const onWebSocketMessage = (e) => {
const data = JSON.parse(e.data);
setEventLog((prev) => [
{
title: data.title,
icon: data.icon,
body: data.body,
date: new Date(),
},
...prev,
]);
setUpdateFlag((prev) => prev + 1);
};
const token = localStorage.getItem("token");
socket = new WebSocket("wss://localhost/" + token);
socket.onmessage = onWebSocketMessage;
}, []);
...
}
Upvotes: 2