skip to Main Content

In my React app I’m fetching an object from my rails backend via an API call that has an array of children objects. Those children objects get built in the background and could take a minute to populate. Rails will update the object when the background worker is completed with a new status. So, the object’s status value will change from "pending" to "completed".

I’d like to either keep running the main API call for the parent object until that value changes or run it every few seconds until it’s changed. And then from there I can update the state of value to show those children objects.

How do I keep running a function to fetch this object until the value changes?

In the code below, the value I’m tracking is data.parts_status

Here’s what my code looks like:

const [loading, setLoading] = useState(true);
const [cabinet, setCabinet] = useState(null);
const [checkParts, setCheckParts] = useState(true);


  useEffect(() => {
    if(loading){
      async function loadCabinet(projectId, cabinetId){
        try {
          const data = await fetchCabinet(projectId, cabinetId);
            setCabinet(data);
            setLoading(false);
            console.log(data);
          } catch (e) {
            console.log(e);
          }
        } loadCabinet(projectId, cabinetId);
      }
    }, [cabinet]);

UPDATE. The useEffect below keeps running despite checkParts being false

  useEffect(() => {
    if(checkParts){
      const interval = setInterval(() => {
        async function loadCabinet(projectId, cabinetId){
          try {
            const data = await fetchCabinet(projectId, cabinetId);
              setCabinet(data);
              setLoading(false);
              if(data.part_status === "completed"){
                setParts(data.parts);
                setCheckParts(false);
              }
              console.log(data);
            } catch (e) {
              console.log(e);
            }
          } loadCabinet(projectId, cabinetId);
      }, MINUTE_MS);
      return () => clearInterval(interval); 
    }
  }, [])

2

Answers


  1. You can use setInterval to accomplish this as follows:

    useEffect(
      () => {
        const intervalId = setInterval(() => {
          // Make your api call/
        }, 1000); // interval in ms
    
        return () => {
          clearInterval(id);
        };
      },
      []
    );
    
    
    Login or Signup to reply.
  2. I noticed that you wrote your solutions like this

      useEffect(() => {
        if(checkParts){
          const interval = setInterval(() => {
            async function loadCabinet(projectId, cabinetId){
              try {
                const data = await fetchCabinet(projectId, cabinetId);
                  setCabinet(data);
                  setLoading(false);
                  if(data.part_status === "completed"){
                    setParts(data.parts);
                    setCheckParts(false);
                  }
                  console.log(data);
                } catch (e) {
                  console.log(e);
                }
              } loadCabinet(projectId, cabinetId);
          }, MINUTE_MS);
          return () => clearInterval(interval); 
        }
      }, [])
    

    this method can retrieve data every MINUTE_MS, but you missed crucial part, the dependency array to stop the interval from running.

      useEffect(() => {
        if(checkParts){
          const interval = setInterval(() => {
            async function loadCabinet(projectId, cabinetId){
              try {
                const data = await fetchCabinet(projectId, cabinetId);
                  setCabinet(data);
                  setLoading(false);
                  if(data.part_status === "completed"){
                    setParts(data.parts);
                    setCheckParts(false);
                  }
                  console.log(data);
                } catch (e) {
                  console.log(e);
                }
              } loadCabinet(projectId, cabinetId);
          }, MINUTE_MS);
          return () => clearInterval(interval); 
        }
     -  }, [])
     +  }, [checkParts]) // do this
    
    

    I do understand checkParts is false after youve done fetching. Without the addition of checkParts in deps array, the useEffect only understand checkParts as true forever.

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