Last active
October 5, 2022 05:58
-
-
Save gragland/d5c183230a78b207ad9d14d38cc8f4f9 to your computer and use it in GitHub Desktop.
Thought process when creating a useToggle() React hook with useState
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Didn't know about useCallback, thanks.