HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptTip

React useEffectOnce hook

Submitted by: @import:30-seconds-of-code··
0
Viewed 0 times
hookuseeffectoncereact

Problem

The way useEffect() works in React is that it runs every time the component renders. Sure, you can control when it runs by providing a dependency array, but what if you want it to run only once when a condition becomes true? You can create a custom hook to achieve this.
As mentioned already, the second argument of the useEffect() hook is an array of dependencies. When any of these dependencies change, the effect runs. By using a useRef() hook to keep track of the execution status of the effect, you can ensure that the effect runs only once when the condition becomes true.
Then, inside the useEffect(), you can check if the condition is true and the effect has not executed before. If both are true, you can run the callback and set the execution status to true.
In order to then use the custom hook, you can pass the callback and the condition as arguments, same as a regular useEffect() call. The custom hook will then run the callback at most once when the condition becomes true the first time.

Solution

const useEffectOnce = (callback, when) => {
  const hasRunOnce = React.useRef(false);

  React.useEffect(() => {
    if (when && !hasRunOnce.current) {
      callback();
      hasRunOnce.current = true;
    }
  }, [when]);
};

const App = () => {
  const [clicked, setClicked] = React.useState(false);
  useEffectOnce(() => {
    console.log('mounted');
  }, clicked);
  return <button onClick={() => setClicked(true)}>Click me</button>;
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <App />
);


Then, inside the useEffect(), you can check if the condition is true and the effect has not executed before. If both are true, you can run the callback and set the execution status to true.
In order to then use the custom hook, you can pass the callback and the condition as arguments, same as a regular useEffect() call. The custom hook will then run the callback at most once when the condition becomes true the first time.

Code Snippets

const useEffectOnce = (callback, when) => {
  const hasRunOnce = React.useRef(false);

  React.useEffect(() => {
    if (when && !hasRunOnce.current) {
      callback();
      hasRunOnce.current = true;
    }
  }, [when]);
};

const App = () => {
  const [clicked, setClicked] = React.useState(false);
  useEffectOnce(() => {
    console.log('mounted');
  }, clicked);
  return <button onClick={() => setClicked(true)}>Click me</button>;
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <App />
);

Context

From 30-seconds-of-code: use-effect-once

Revisions (0)

No revisions yet.