Understanding useCallback and Building a Custom Countdown Hook in React
This article explores the purpose and proper usage of React's useCallback hook, examines common pitfalls, and demonstrates how to build and enhance a reusable countdown custom hook, including handling callbacks, effect dependencies, and ref-based solutions for stable function references.
Introduction: The author reflects on recent insights about useCallback and a friend's interview question about implementing a countdown hook, prompting a deeper understanding of React hooks.
Discussion on why many open‑source hooks store parameters in ref objects and access them via .current , noting the extra complexity compared to using plain variables.
Explanation of when to use useCallback :
Stage 1 – discovering that useCallback can cache a function to prevent it from being recreated on every render, which helps avoid infinite loops in useEffect dependency arrays.
Stage 2 – assuming that caching always improves performance, leading to over‑use of useCallback together with memo for child components.
Stage 3 – realizing that unnecessary caching can be counter‑productive because the overhead may outweigh the benefits.
Key takeaways from each stage are highlighted, emphasizing that useCallback should be applied judiciously.
Summary of proper scenarios for useCallback :
When a parent component passes a function prop to a memoized child component, the function should be wrapped with useCallback to keep the prop stable.
When a function appears in a useEffect dependency array, wrapping it with useCallback prevents the effect from running endlessly.
When a custom hook returns a function that may be used as a useEffect dependency, the returned function should be memoized with useCallback .
Implementation of a custom useCountdown hook is presented:
The hook accepts a duration and returns the current count and a start function.
Initial version creates a timer in a button component; the logic is extracted into the hook.
Later the hook is upgraded to accept optional callbacks for each tick and for completion, using a configuration object with countdownCallBack and onEnd .
To avoid stale references for external callbacks, the solution employs useRef (or utilities like useLatest / useMemoizedFn from the ahooks library) to store the latest versions without adding them to the useEffect dependency array.
Final conclusions reiterate two core points: a refreshed understanding of useCallback (and its sibling useMemo ) usage scenarios, and best practices for writing custom hooks that safely handle external inputs and provide reliable outputs.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.