1

I want to do this

  useEffect(() => {
    if (!datasetsState.list.length) {
      dispatch({ type: DatasetsActionTypes.FETCH, payload: {} });
    }
  }, [datasetsState, dispatch]);

but dispatch({ type: DatasetsActionTypes.FETCH, payload: {} }); causes update of datasetsState which will cause forever loop if datasetsState.list stay empty after response

One of the solutions to my problem is to remove datasetsState from the dependency array, but I will get react exhaustive-deps warning which I want to avoid.

And the following code will work for me also and don't cause any warnings. But it is an ugly and complex solution for a pretty common problem I think.

const [isDoneOnce, setIsDoneOnce] = useState(false);
  useEffect(() => {
    if (isDoneOnce) {
      return;
    }
    if (!datasetsState.list.length) {
      dispatch({ type: DatasetsActionTypes.FETCH, payload: {} });
    }
    setIsDoneOnce(true);
  }, [datasetsState, dispatch]);

How can I prevent useEffect from updating without using additional variables like isDoneOnce ?

Rob Minasyan
  • 390
  • 2
  • 14

2 Answers2

1

You should use a "global" variable or a reference.

Which one to choose depends on the context, check this answer about the differences.

TL;DR - Depends on the context of "run once", application life or component's life.

Reference:

const App = () => {
  const isDoneRef = useRef(false);

  useEffect(() => {
    if (!isDoneRef.current) {
      dispatch({ type: DatasetsActionTypes.FETCH, payload: {} });
      isDoneRef.current = true;
    }
  }, [dispatch]);

  return <></>;
};

Variable:

let isDoneGlobal = false;

const App = () => {
  useEffect(() => {
    if (!isDoneGlobal) {
      dispatch({ type: DatasetsActionTypes.FETCH, payload: {} });
      isDoneGlobal = true;
    }
  }, [dispatch]);

  return <></>;
};
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
1

Make sure to depend on the actual value used inside useEffect, e.g.:

const len = datasetsState.list.length

useEffect(() => {
  if (!len) {
    dispatch(...)
  }
}, [len, dispatch])
Aprillion
  • 21,510
  • 5
  • 55
  • 89