Unwanted thunk double-dispatch on useEffect with React 18 StrictMode

Viewed 541

I'm trying to dispatch a thunk on a first render of the page and on a button click. Here's a sample code of it:

export default function App() {
  const [loading, setLoading] = useState(false);
  const [finished, setFinished] = useState(false);
  const count = useSelector(countSelector);
  const dispatch = useDispatch();

  const appendCounter = useCallback(() => {
    if (!loading) {
      setLoading(true);
      setFinished(false);

      dispatch(thunk()).finally(() => {
        setLoading(false);
        setFinished(true);
      });
    }
  }, [loading, dispatch]);

  useEffect(() => {
    if (!loading && !finished) {
      appendCounter();
    }
  }, [appendCounter, loading, finished]);

  return (
    <div className="App">
      {!loading && finished ? (
        <>
          <h2>{count}</h2>
          <button onClick={appendCounter}>Append</button>
        </>
      ) : (
        <h2>loading</h2>
      )}
    </div>
  );
}
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

I'm using React 18 with StrictMode. On React 17 everything works fine, but on 18 I'm getting two dispatched thunks on the page render. I think that's due to StrictMode changes in React 18. How can I fix the code to prevent double-dispatching? The code is also available on CodeSandbox.

0 Answers
Related