I am new to frontend programming and am given a React codebase to update.
What I want to do is to allow the user to click a button to POST some data to the backend and continuously stream data from the backend and update the frontend continuously as data is being received. (For now, I’m console logging the received data) I’m using Javascript stream reader for this task.
The expected behaviour is that the data is console logged as each chunk of data is arrived but the observed behaviour is that the reader waits until the stream is closed and then console log the values. I can’t figure out why. In all examples I see, the reader continues after one chunk is received.
The following is the relevant code. It contains an upload button and a confirm button. Pressing confirm button submits the previously uploaded data.
const UploadActions = (props: UploadActionsProps) => {
const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
const [loadSwitch, setLoadSwitch] = useState<boolean>(false);
const {authToken} = useContext(AuthTokenContext);
const {
isObjectUploaded, setIsObjectUploaded,
uploadObjects, setUploadObjects,
uploadObjectErr, setUploadObjectErr
} = useContext(UploadObjectContext) as DataTransferObjectContextType;
useEffect(() => {
(async () => {
// uploadObjects contain data uploaded in a previous page
if (!isObjectUploaded || uploadObjects.length === 0 || !loadSwitch){
return
}
const url = `/add/data`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'text/event-stream',
"authenticity-token": authToken
},
body: JSON.stringify(uploadObjects)
});
// Check if the response is a readable stream
if (response.body) {
const reader = response.body.getReader();
const decoder = new TextDecoder();
let done = false;
// Read the stream in chunks and process them
while (!done) {
const { value, done: doneReading } = await reader.read(); // this is where the problem is. The while loop does not continue until done is set
done = doneReading;
// Decode the chunk into text
const chunk = decoder.decode(value, { stream: true });
console.log(chunk)
}
console.log("done reading values")
} else {
console.error('Stream is not available');
}
})();
}, [loadSwitch]);
const handleUploadActions = (confirmation: boolean): void => {
if (confirmation) {
setLoadSwitch(true)
}
setIsDialogOpen(!isDialogOpen);
}
return (
{/* submit button. When this is pressed confirmation appears */}
<Button
onClick={() => {setIsDialogOpen(true); setLoadSwitch(false)}}
sx={styles.saveButton}
>
<Typography sx={styles.buttonText}>Save Data</Typography>
</Button>
{/* confirmation button. When clicked handleUploadActions function gets triggered */}
{isDialogOpen &&
<ConfirmationDialog
handleAction={handleUploadActions}
submitLabel={"Yes I'm sure"}
dialogTitle={"Are you sure you want to save?"}
>
</ConfirmationDialog>
}
);
};
export default UploadActions;
I’m just wondering if this is a problem with state handling in React. But I really don’t know how that can be.
Any help is appreciated.
–PPGoodman