Explain Codes LogoExplain Codes Logo

Make React useEffect hook not run on initial render

javascript
use-effect
react-hooks
optimization
Anton ShumikhinbyAnton ShumikhinยทOct 17, 2024
โšกTLDR
const useUpdateEffect = (effect, deps) => { const isInitialMount = useRef(true); useEffect(() => { if (isInitialMount.current) { isInitialMount.current = false; } else { return effect(); } }, deps); } // Usage Example useUpdateEffect(() => { // Your code which absolutely don't want to be a first child ๐Ÿ˜Ž }, [/* dependencies */]);

This custom hook, useUpdateEffect will come to the rescue for effects that skip the initial render. It uses useRef to distinguish between the initial mount and further updates.

Using useRef for tracking initial render

The useRef hook creates a mutable object reference, which is excellent for tracking the initial render:

const firstRender = useRef(true); useEffect(() => { if (firstRender.current) { firstRender.current = false; // This render grew! } else { // Your effect code here } }, []);

This means useRef will store the first render value and won't trigger a re-render, which makes it mostly unregister in this family. It just sits alone in the corner and tracks things without getting in the way.

Synchronization layout effects

useLayoutEffect lets your effect run synchronously after all DOM mutations. This brings the same family traits as componentDidUpdate, ensuring effects are synchronized with UI updates.

const useUpdateLayoutEffect = (effect, deps) => { const isInitialMount = useRef(true); useLayoutEffect(() => { if (isInitialMount.current) { isInitialMount.current = false; } else { effect(); // This can be your super-binocular synchronously spying on UI changes. } }, deps); };

Just remember, with great power, comes great responsibility๐Ÿ˜‰. Make sure your effects don't block the UI thread and get someone mad at you.

Mastering useEffect like a pro!

Keeping functions cool with unmounting

Always remember to stay cool๐ŸงŠ and clean up when your effect has done its job - Unmount your functions within effects:

useEffect(() => { return () => { // Time to clean up! }; }, []);

Persistence is key

If you have data you need to persist across renders, useRef got your back:

const lastExecution = useRef(Date.now()); useEffect(() => { if (Date.now() - lastExecution.current > 1000) { // This is the moment! lastExecution.current = Date.now(); } }, [/* dependencies */]);