Frontend Development 16 min read

Advanced Tips and Common Pitfalls for React Hooks (useState, useEffect, useContext, useReducer, etc.)

This article provides in‑depth guidance on using React hooks such as useState, useEffect, useContext, useReducer, and related utilities, covering lazy initialization, functional updates, performance‑optimising patterns, state sharing strategies, and advanced techniques like useImmer and react‑tracked to reduce mental overhead and avoid bugs.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Advanced Tips and Common Pitfalls for React Hooks (useState, useEffect, useContext, useReducer, etc.)

useState – The most frequently used hook can be optimised by using lazy initialisation to avoid recomputing heavy values on every render, and by applying functional updates to prevent stale‑closure bugs when state is updated inside asynchronous callbacks.

const [state, setState] = useState(0);
// Lazy initialisation
const [state, setState] = useState(() => heavyCompute());
// Functional update
setState(prev => prev + 1);

When dealing with nested objects, manually spreading state creates a heavy mental load; useImmer (or its sugar useImmer ) lets you mutate a draft object while preserving immutable updates, providing copy‑on‑write semantics and better performance.

const [state, setState] = useImmer({ a: 1, b: { c: [1, 2] } });
setState(draft => { draft.b.c.push(3); });

useEffect – Avoid using it as a generic watch; instead, keep state updates inside event handlers or effects with an empty dependency array. Remember that setting state inside an effect will re‑run the component, so proper dependency management is crucial to prevent infinite loops.

useEffect(() => {
  const timer = setInterval(() => setState(prev => prev + 1), 1000);
  return () => clearInterval(timer);
}, []);

When many components share a context, every update causes all consumers to re‑render. react‑tracked replaces the vanilla useContext pattern with a proxy‑based solution that tracks component‑level usage and updates only the parts that actually depend on changed state.

import { createContainer } from 'react-tracked';
const { Provider, useTracked } = createContainer(() => useState({ count: 0 }));

useCallback – Overusing it adds unnecessary complexity; prefer it only when you need a stable function reference (e.g., for event listeners). For most cases, useMemoizedFn from ahooks offers a simpler way to keep the same function identity while still accessing the latest state.

const fn = useMemoizedFn(() => console.log(state));

memo & useMemo – React.memo shallowly compares props, while useMemo memoises a value based on dependencies. Combining them with immutable state helpers (useImmer) and stable callbacks (useMemoizedFn) yields fine‑grained render control without excessive boilerplate.

const MemoizedChild = React.memo(({ a }) =>
);
const child = useMemo(() =>
, [a]);

useReducer – For more complex state transitions, move the logic into a pure reducer function. This separates state mutation from UI code, making the component easier to maintain. Async side‑effects can be handled with libraries like use-reducer-async .

function reducer(state, action) {
  switch (action.type) {
    case 'start': return { ...state, isRunning: true };
    case 'stop':  return { ...state, isRunning: false };
    case 'reset': return { isRunning: false, time: 0 };
    case 'tick':  return { ...state, time: state.time + 1 };
    default: throw new Error('unknown action');
  }
}
const [state, dispatch] = useReducer(reducer, { isRunning: false, time: 0 });

The article concludes that React hooks, while powerful, impose a significant mental burden, and hopes that tools like react‑forget will soon become production‑ready to alleviate this complexity.

performanceReactHooksuseReduceruseEffectuseStateuseContext
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.