The Road to Next — your interactive course for Next.js with React

React useEffect only Once

Robin Wieruch

If you are wondering how to run React’s useEffect Hook only once, you may be surprised that you need React’s useRef Hook as helper to create an instance variable for tracking the component’s lifecycle. The following code shows you how to achieve it:

javascript
import * as React from 'react';

const App = () => {
  const [toggle, setToggle] = React.useState(true);

  const handleToggle = () => {
    setToggle(!toggle);
  };

  const calledOnce = React.useRef(false);

  React.useEffect(() => {
    if (calledOnce.current) {
      return;
    }

    if (toggle === false) {
      console.log('I run only once if toggle is false.');

      calledOnce.current = true;
    }
  }, [toggle]);

  return (
    <div>
      <button type="button" onClick={handleToggle}>
        Toggle
      </button>

      {toggle && <div>Hello React</div>}
    </div>
  );
};

export default App;

If you want to have a reusable custom hook for it, which only triggers the effect function once (and not on mount), you can use the following hook for it:

javascript
import * as React from 'react';

const useEffectOnlyOnce = (callback, dependencies, condition) => {
  const calledOnce = React.useRef(false);

  React.useEffect(() => {
    if (calledOnce.current) {
      return;
    }

    if (condition(dependencies)) {
      callback(dependencies);

      calledOnce.current = true;
    }
  }, [callback, condition, dependencies]);
};

const App = () => {
  const [toggle, setToggle] = React.useState(true);

  const handleToggle = () => {
    setToggle(!toggle);
  };

  useEffectOnlyOnce(
    (dependencies) => {
      console.log('I run only once if toggle is false.');
    },
    [toggle],
    (dependencies) => dependencies[0] === false
  );

  return (
    <div>
      <button type="button" onClick={handleToggle}>
        Toggle
      </button>

      {toggle && <div>Hello React</div>}
    </div>
  );
};

export default App;

That’s it. React’s useEffect Hook doesn’t come with a feature to run it only once, however, this custom hook should help you to accomplish it. Let me know if this helps you.

Never Miss an Article

Join 50,000+ developers getting weekly insights on full-stack engineering and AI.

AI Agentic UI Architecture React Next.js TypeScript Node.js Full-Stack Monorepos Product Engineering
Subscribe on Substack

High signal, low noise. Unsubscribe at any time.