I am new to ReactJs .I’m trying to use the useState hook in react function base component but the value of the state is not getting updated when I am calling the function. When receiving data via websocket, it is not possible to update the data on the line graph using the construct useState and useEffect.
client receives data via websocket:
const myWs = new WebSocket('ws://localhost:8000');
// обработчик проинформирует в консоль когда соединение установится
myWs.onopen = function () {
console.log('подключился');
};
// обработчик сообщений от сервера
myWs.onmessage = function (message) {
const jsonParse = JSON.parse(message.data);
try {
let temp = {x:setInterval((counter) =>{
if(mockLineData[0].data.length >= 50){
mockLineData[0].data.shift();
counter++
}
else{
counter++
}
}, 3000), y:jsonParse[0]['value_state']};
mockLineData[0].data.push(temp);
console.log(mockLineData[0].data);
} catch (error) {
console.log('Error: ', error);
}
};
export const mockLineData = [
{
id: "ИБП Uвх",
color: tokens("dark").redAccent[200],
data: [
{
x: 0,
y: 0
},
],
},
];
Next I’m trying to update data in a table using the construct useState and useEffect
import { mockLineData as data } from "../data/dataLineGraph";
const LineChart = ({ isCustomLineColors = false, isDashboard = false }) => {
const theme = useTheme();
const colors = tokens(theme.palette.mode);
const [state, setState] = useState();
useEffect(() => {
setInterval(()=>{
setState(data);
},1000)
}, []);
return (
<ResponsiveLine
data={state}
theme={{
axis: {
domain: {
line: {
stroke: colors.grey[100],
},
},
legend: {
text: {
fill: colors.grey[100],
},
},
ticks: {
line: {
stroke: colors.grey[100],
strokeWidth: 1,
},
text: {
fill: colors.grey[100],
},
},
},
legends: {
text: {
fill: colors.grey[100],
},
},
tooltip: {
container: {
color: colors.primary[500],
},
},
}}
colors={isDashboard ? { datum: "color" } : { scheme: "nivo" }} // added
margin={{ top: 50, right: 110, bottom: 50, left: 60 }}
enableGridX={false}
enableGridY={false}
pointSize={8}
pointColor={{ theme: "background" }}
pointBorderWidth={2}
pointBorderColor={{ from: "serieColor" }}
pointLabelYOffset={-12}
useMesh={true}
legends={[
{
anchor: "bottom-right",
direction: "column",
justify: false,
translateX: 100,
translateY: 0,
itemsSpacing: 0,
itemDirection: "left-to-right",
itemWidth: 80,
itemHeight: 20,
itemOpacity: 0.75,
symbolSize: 12,
symbolShape: "circle",
symbolBorderColor: "rgba(0, 0, 0, .5)",
effects: [
{
on: "hover", //hover
style: {
itemBackground: "rgba(0, 0, 0, .03)",
itemOpacity: 1,
},
},
],
},
]}
/>
);
};
export default LineChart;
but the data is not updated
3
Answers
Your
useEffect
closes overdata
once (empty dependency array) – hence data will always be the same object, and nothing ever gets changed even if you repeatedly callsetInterval
.once you didn’t send
data
toLineChart
.if you get it from Parent Component – add it to
props
:second – if your data changed due to lifecycle, your
useEffect
need to includedata
independencies array
.so on every change in
data
will notify byuseEffect
.change your
useEffect
to:finally your code will be seemed:
Why does my code not work?
At first you set the variable
data
just in youruseEffect
hook, but where did your component get this variable? You don’t initialize this variable in your LineChart component or declare this dependency as a LineChart prop so that the component get thedata
from it’s parent.Lets start with the question should your
LineChart
component be aSmart
orDumb
react component (here is a good article if your not familier with this terms https://medium.com/@thejasonfile/dumb-components-and-smart-components-e7b33a698d43)I would say your
LineChart
component is aDumb
component, which just displays yourdata
and has no business logic to get thedata
directly from the websocket.Because of this we will introduce your
data
as aLineChart
prop without using anyuseState
oruseEffect
hooks. Maybe you are thinking now, how should the component update when we don’t use astate
combined withuseEffect
. Thats quite simple – Your component rerenders automatically when a prop changes as well.So lets solve your problem by modifying
LineChart
:With this component you just have to pass your new
data
as prop to yourLineChart
and your component will be updated.My recommendation: Don’t mix props with the component state as long your component just uses the prop for reading/display information.