clean-react-hooks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Clean Hooks

整洁的Hooks

Hooks should make stateful behavior explicit. Effects are for synchronization with systems outside React, not for deriving ordinary render data.
Hooks应使有状态行为清晰明确。Effect用于与React外部系统同步,而非推导普通渲染数据。

R4: Effects

R4: Effects

Use
useEffect
for:
  • Subscriptions and cleanup
  • Browser APIs and imperative widgets
  • Network calls when the project does not use a data-fetching library
  • Synchronizing React state with an external system
Do not use
useEffect
for values that can be computed during render.
tsx
// Bad - derived state via effect
const [fullName, setFullName] = useState("");

useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

// Good - derived during render
const fullName = `${firstName} ${lastName}`;
使用
useEffect
的场景:
  • 订阅及清理操作
  • 浏览器API和命令式组件
  • 项目未使用数据获取库时的网络请求
  • 将React状态与外部系统同步
不要将
useEffect
用于可在渲染期间计算的值。
tsx
// Bad - derived state via effect
const [fullName, setFullName] = useState("");

useEffect(() => {
  setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);

// Good - derived during render
const fullName = `${firstName} ${lastName}`;

Dependencies

依赖项

  • Treat the dependency array as a correctness contract.
  • Do not suppress exhaustive-deps without explaining the external invariant.
  • Stabilize callbacks only when identity matters to a child, subscription, or memoized computation.
  • Prefer moving logic inside the effect over hiding dependencies.
  • 将依赖数组视为正确性契约。
  • 不要在未说明外部不变量的情况下禁用exhaustive-deps检查。
  • 仅当回调的标识对子组件、订阅或记忆化计算至关重要时,才稳定回调。
  • 优先将逻辑移至effect内部,而非隐藏依赖项。

R8: Custom Hooks

R8: 自定义Hooks

Create a custom hook when behavior is reusable and stateful, or when it gives a complex effect a clear boundary.
tsx
function useWindowSize(): WindowSize {
  const [size, setSize] = useState(getWindowSize);

  useEffect(() => {
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);

    function handleResize() {
      setSize(getWindowSize());
    }
  }, []);

  return size;
}
Keep hook APIs small. Return named objects for multiple values unless tuple ordering is a local convention.
当行为可复用且带有状态,或需要为复杂effect划分清晰边界时,创建自定义hook。
tsx
function useWindowSize(): WindowSize {
  const [size, setSize] = useState(getWindowSize);

  useEffect(() => {
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);

    function handleResize() {
      setSize(getWindowSize());
    }
  }, []);

  return size;
}
保持hook的API简洁。除非元组排序是本地约定,否则返回命名对象以包含多个值。

Refs

Refs

Use refs for imperative handles, DOM nodes, and mutable values that should not trigger render. Do not use refs to sidestep normal state flow.
使用refs处理命令式句柄、DOM节点以及不应触发渲染的可变值。不要使用refs规避正常的状态流。

Common Mistakes

常见错误

  • Using effects to copy props into state.
  • Adding empty dependency arrays to "run once" while reading changing values.
  • Using
    useMemo
    or
    useCallback
    everywhere without a measured reason.
  • Returning unstable object shapes from hooks that consumers put into dependency arrays.
  • 使用effect将props复制到state中。
  • 添加空依赖数组以“仅运行一次”,却读取变化的值。
  • 无合理依据地到处使用
    useMemo
    useCallback
  • 从hook返回不稳定的对象结构,而消费者会将其放入依赖数组中。