高级 React 开发者应该如何思考 Hooks
大多数开发者在学习 Hooks 时并不理解 React 的渲染机制,这会导致困惑。要精通 Hooks,你必须理解五个核心职责:
• 记忆数据 • 执行副作用 • 共享数据 • 优化渲染 • 控制调度
状态变化会触发重新渲染。每一次重新渲染都会重新创建变量、对象和函数。这个简单的事实解释了为什么需要 useMemo 和 useCallback。
理解 Hooks
状态与顺序 React 将状态存储在附加到组件 Fiber 上的链表中。这就是为什么你不能在条件语句或循环中调用 Hooks。React 依赖于调用顺序来查找正确的状态。
批处理的现实
当你调用 setState 时,React 会调度一次更新。它不会立即改变值。这就是为什么在设置状态后立即打印状态会显示旧值。请始终使用函数式更新模式来避免陈旧数据:
- 错误:
setCount(count + 1) - 正确:
setCount(prev => prev + 1)
useEffect 的心智模型
不要再把 useEffect 当作生命周期方法来对待。应该使用它来使你的组件与外部系统(如 API 或 WebSockets)保持同步。
重要提示:React 会在 useEffect 运行之前进行屏幕绘制。这确保了你的 effect 不会阻塞 UI。如果你需要在用户看到之前测量 DOM,请使用 useLayoutEffect。
useRef 的现实
Ref 不仅仅是为了 DOM 元素。它是一个持久的可变容器。React 在渲染之间保持相同的对象引用。修改 ref.current 不会触发重新渲染。可以将其用于定时器、Socket 或存储前一次的值。
记忆化陷阱
useMemo 并不是提升速度的万能按钮。它是有开销的。React 必须存储缓存并比较依赖项。
只有当计算成本高于记忆化成本时,才使用 useMemo。如果你将其用于简单的数学运算,反而会让你的应用变慢。
Context 不是状态管理 Context 是用于依赖注入的。它能帮你避免 Prop Drilling(属性钻取)。然而,当 Context 的值发生变化时,每个消费者都会重新渲染。不要将整个全局状态都放在一个 Provider 中。请根据用途拆分你的 Context。
高级模式
• useReducer:对于复杂的状态机,请使用它,而不是调用许多 useState。
• startTransition:使用它来确保在进行繁重更新时 UI 仍能保持响应。
• useDeferredValue:在用户输入时,使用它来延迟昂贵的 UI 更新。
通过将逻辑移入自定义 hooks 来编写整洁的代码。一个 1200 行的组件很难维护,而五个承载逻辑的小型 hooks 则易于扩展。
来源:https://dev.to/jagadeesh_008/how-advanced-react-developers-should-think-about-hooks-102l