I have a state variable in my react app that stores an array of objects which are sent from a flask server then rendered in a list on the page. Inside one of my functions I need to access this array but whenever I try to use this value I get an empty list even though I can see the values in the array being rendered on the page.
This is the function that is attempting to access the events state array but the line
let newEvent = { ...events[0] };
is initializing newEvent to {}.
const addEvent = (action_event: any) => {
const transformedEvent = {
...JSON.parse(action_event),
camera: "Face",
};
if (parseInt(transformedEvent.cont)) {
let newEvent = { ...events[0] };
newEvent.frameEnd = transformedEvent.frameEnd;
setEvents((events) => [newEvent].concat(events.slice(1)));
} else {
delete transformedEvent.cont;
setEvents((events) => [transformedEvent].concat(events));
}
};
For some context if (parseInt(transformedEvent.cont))
will never be true before the else block is called so events should always have at least one element
I’m rendering the array with the following code:
{events.map((event, index) => (
<Box key={index} className={styles.liveClasBox}>
<Typography
textAlign={"center"}
width={150}
textTransform={"capitalize"}
>
{event.label.replaceAll("_", " ")}
</Typography>
<Divider orientation="vertical" flexItem />
<Typography
textAlign={"center"}
width={150}
>{`From: Frame #${event.frameStart}`}</Typography>
<Divider orientation="vertical" flexItem />
<Typography
textAlign={"center"}
width={150}
>{`To: Frame #${event.frameEnd}`}</Typography>
</Box>
))}
I’ve tried accessing the events array in different functions but its always empty with a length of 0. I read a post about a similar issue and that issue was caused by mutating the state array without using the update function (setEvents) but I don’t believe I’m doing that anywhere. I’ve included the full code file below in case I’m missing something
"use client";
import React, { useState, useEffect, act } from "react";
import { Box, Typography, Divider } from "@mui/material";
import styles from "./page.module.css";
import { LiveFrame, Event } from "./types";
export default function Demo() {
const [livePredictStream, setLivePredictStream] = useState<LiveFrame[]>([]);
const [events, setEvents] = useState<Event[]>([]);
const [frame, setFrame] = useState(null);
useEffect(() => {
const eventSource = new EventSource(`http://127.0.0.1:5000/video_feed`);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.action_event != 0) {
addEvent(data.action_event.replaceAll("'", '"'));
setFrame(data.image);
}
addLivePredictions(data.actions_predictions, data.first_frame_num);
};
return () => {
eventSource.close();
};
}, []);
const addEvent = (action_event: any) => {
const transformedEvent = {
...JSON.parse(action_event),
camera: "Face",
};
if (parseInt(transformedEvent.cont)) {
let newEvent = { ...events[0] };
newEvent.frameEnd = transformedEvent.frameEnd;
setEvents((events) => [newEvent].concat(events.slice(1)));
} else {
delete transformedEvent.cont;
setEvents((events) => [transformedEvent].concat(events));
}
};
const addLivePredictions = (predictions: string[], startingFrame: string) => {
const transformPredictions: LiveFrame[] = predictions.map(
(prediction, index) => ({
value: prediction,
frameNum: parseInt(startingFrame) + index,
camera: "Face",
})
);
transformPredictions.reverse();
setLivePredictStream((livePredictStream) =>
[...transformPredictions].concat(livePredictStream)
);
};
const removeLivePredictions = () => {
let tempArr = livePredictStream.slice(0, 30);
setLivePredictStream(tempArr);
};
useEffect(() => {
if (livePredictStream.length > 150) {
removeLivePredictions();
}
}, [livePredictStream]);
const videoSource = frame
? URL.createObjectURL(new Blob([frame], { type: "image/jpeg" }))
: "";
return (
<Box className={styles.pageContainer}>
<Box className={styles.cameraContainer}>
<Box>
<Typography variant="h6" textAlign="center">
Face Cam
</Typography>
<Box className={styles.cameraWrapper}>
<video
src={videoSource}
className={styles.video}
autoPlay
width={300}
height={300}
/>
</Box>
</Box>
{/* <Box>
<Typography variant="h6" textAlign="center">
Body Cam
</Typography>
<Box className={styles.cameraWrapper}>BODY</Box>
</Box> */}
</Box>
<Box className={styles.listContainer}>
<Box className={styles.liveClasContainer}>
<Typography variant="h5" textAlign={"center"} fontWeight={500}>
Event Feed
</Typography>
{events.map((event, index) => (
<Box key={index} className={styles.liveClasBox}>
<Typography
textAlign={"center"}
width={150}
textTransform={"capitalize"}
>
{event.label.replaceAll("_", " ")}
</Typography>
<Divider orientation="vertical" flexItem />
<Typography
textAlign={"center"}
width={150}
>{`From: Frame #${event.frameStart}`}</Typography>
<Divider orientation="vertical" flexItem />
<Typography
textAlign={"center"}
width={150}
>{`To: Frame #${event.frameEnd}`}</Typography>
</Box>
))}
</Box>
<Box className={styles.liveClasContainer}>
<Typography variant="h5" textAlign={"center"} fontWeight={500}>
Live Frame Classification
</Typography>
{livePredictStream.map((prediction, index) => (
<Box key={index} className={styles.liveClasBox}>
<Typography
textAlign={"center"}
width={150}
>{`Frame #${prediction.frameNum}`}</Typography>
<Divider orientation="vertical" flexItem />
<Typography textAlign={"center"} width={150}>
{prediction.value}
</Typography>
</Box>
))}
</Box>
</Box>
</Box>
);
}
Isaiah Richards is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.