skip to Main Content

I have 2 different useEffect:

  useEffect(() => {
    return () => {
      setElements(undefined);
    };
  }, [elementParam]);

  useEffect(() => {
    if (currentlyFetchedElements) {
      setElements(previouslyFetchedElements => ({ ...previouslyFetchedElements, ...currentlyFetchedElements }));
    }
  }, [currentlyFetchedElements]);
  • The idea of the 1st useEffect is to "restart" the elements state, whenever elementParam updates.
  • When elementParam updates, it also triggers and API call that updates currentlyFetchedElements

The problem:
If I mess with elementParam long enough, there’s a point where the currentlyFetchedElements API call is cached, and the 2nd use effect takes place before the 1st one, and i see elements as undefined when they’re not.

NOTE: I don’t want to setElements(undefined); always, just if elementParam it’s updated, bc i’m using elements to accumulate the API responses(that’s why i have 2 different useEffects)

How can i fix this?

The only work around i’ve found so far is adding a setTimeout to the 2nd useEffect to make sure it takes place after the 1st one but i know there should be a better way

2

Answers


  1. You can use one useEffect instead!

    Check the following code:

    useEffect(() => {
      setElements(undefined);
    
      if (currentlyFetchedElements) {
        setElements(previouslyFetchedElements => ({
          ...previouslyFetchedElements,
          ...currentlyFetchedElements
        }));
      }
    }, [elementParam, currentlyFetchedElements]);
    
    Login or Signup to reply.
  2. Personally I would use one useEffect that depends on both elementParam and currentlyFetchedElements.

    That way, this effect is fired when either of those dependencies change. Here you can use a boolean useState as a flag that ensures that the second method fires only after the first one is done, like:

    const [doneSettingElements, settingElementsFlag] = useState(false);
    
    useEffect(() => {
    
      return () => {
        setElements(undefined);
        settingElementsFlag(true);
      };
    
      if (currentlyFetchedElements && doneSettingElements) 
      {
        setElements(previouslyFetchedElements => ({ ...previouslyFetchedElements, ...currentlyFetchedElements }));
      }
    
    }, [elementParam, currentlyFetchedElements]);
    
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search