Skip to content

Instantly share code, notes, and snippets.

@gragland
Last active October 5, 2022 05:58
Show Gist options
  • Save gragland/d5c183230a78b207ad9d14d38cc8f4f9 to your computer and use it in GitHub Desktop.
Save gragland/d5c183230a78b207ad9d14d38cc8f4f9 to your computer and use it in GitHub Desktop.
Thought process when creating a useToggle() React hook with useState
import { useState, useCallback } from "react";
function useToggle(initialValue = false){
// State with initial boolean value (true/false)
const [state, setState] = useState(initialValue);
// Let's create a toggle function
// This works, but we're using the state value from above
// instead of the current state. Usually they are the same,
// but if this hook was triggered multiple times rapidly then
// state value above might actually be stale.
❌ const toggle = () => setState(!state);
// Okay, problem solved. We're now using the function argument format
// of useState so that we're always reading the current state.
// But we have another problem. We're creating a new function on every render.
// The concern isn't that creating new function is expensive,
// but rather that if toggle() gets passed to child components it could
// cause them to re-render if the function is new every time.
❌ const toggle = () => setState((currentState) => !currentState);
// No problem. That's what useCallback is for.
// Our toggle function is now only created once on mount. Hurray 🎉
✅ const toggle = useCallback(() => setState((currentState) => !currentState), []);
return [state, toggle];
}
@adisa-di
Copy link

This is cool - thanks 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment