skip to Main Content

I have a modal that does some async logic submitting to a database.

My LinearDeterminate component looks like this (using MUI):
MUI Progress

import { useEffect, useState } from "react";
import Box from "@mui/material/Box";
import LinearProgress from "@mui/material/LinearProgress";

export default function LinearDeterminate({ doneSoFar, allData }) {
  const [progress, setProgress] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setProgress((prevProgress) => {
        if (prevProgress >= 100) {
          return 0;
        }
        return (doneSoFar / allData.length) * 100;
      });
    }, 500);

    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <Box sx={{ width: "100%", mt: 2 }}>
      <LinearProgress variant="determinate" value={progress} />
    </Box>
  );
}

I’m using it in this modal:

import LinearDeterminate from "./LinearDeterminate";

export default function MyModal() {
  const data = []; // my data here
  let done = 0;

  const handleFunc = async () => {
    try {
      const promises = [];
      for (const row of data) {
        // some logic here
        done++; // incrementing done when every row is done
      }

      await Promise.all(promises);
    } catch (error) {}
  };
  return <LinearDeterminate doneSoFar={done} allData={data} />;
}

The problem is that the progress bar isn’t moving at all. When console logging done it is incrementing correctly. What am I doing wrong here?

2

Answers


  1. In my opinion, you need to set done and data to state values in MyModal.

    For example:

    const [done, setDone] = useState(0);
    const [data, setData] = useState(0);
    
    setDone(prevDone => prevDone + 1);
    setData(prevData => [...prevData, row]);
    

    And you can try to debug doneSoFar value in LinearDeterminate component. For example:

    console.log(doneSoFar);
    

    And then, add doneSoFar and allData to useEffect hook dependencies in your LinearDeterminate component, for example:

    useEffect(() => {
      setProgress((prevProgress) => {
        if (prevProgress >= 100) {
          return 0;
        }
        return (doneSoFar / allData.length) * 100;
      });
    }, [doneSoFar, allData]);
    
    Login or Signup to reply.
  2. you can try this:

    const [progress, setProgress] = useState(0);
    //..
    useEffect(() => {
      const newProgress = (doneSoFar / allData.length) * 100;
      setProgress(newProgress);
    }, [doneSoFar, allData]);
    

    useEffect has [doneSoFar, allData] as dependency array. so whenever doneSoFar or allData changes, the effect will fire. inside useEffect the progress state is updated based on the new values of doneSoFar and allData.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search