I often find myself needing to prevent useEffect from running on the initial render and only triggering it when dependencies change. To make this easier, I want to create a custom hook that handles this. How can I create such a hook in React?
This is my code:
import React, { useState, useEffect } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
// i want to save the count variable only when count is updated
localStorage.setItem('count', count + '') // but it set the localStorage count to 0, making my code useless
}, [count]);
useEffect(() => {
// load save count if available
let count = localStorage.getItem('count')
if(count) {
setCount(parseInt(count))
}
}, [])
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
This code saves count
into the localstorage every time the component loads, so count is set to 0
every time, and when its time to load the count variable from the localStorage, it reads 0
How can I create a React hook to run effectful code only when one of the deps change?
3
Answers
This sounds like an X/Y problem. If you want to only save the count variable when it’s updated, wrap
setCount
accordingly.Something like this…
You can simply return false if count is equal to 0 (first useEffect call on mount)
You want a ref to track whether the component has mounted.
The Hook
Example Usage
The
useUpdateEffect
hook can be used similarly touseEffect
, but it will skip execution on the component’s initial render due to the if statement at the topIf you’re wondering about why I decided to return the
callback
, this is for whenever you need to run a clean up when the component unmounts to prevent a memory leak.