Skip to content

一、状态管理实战模式

1️⃣ 局部状态 vs 全局状态拆分原则

✅ 局部状态(优先)

  • 表单
  • 弹窗开关
  • hover / loading
  • 局部 UI 状态

用:

js
useState
useReducer

原则:

状态尽量靠近使用它的组件

✅ 全局状态

不要滥用 Context。

推荐:

  • 轻量场景:Context + selector
  • 中大型项目:zustand / jotai
  • 超复杂:redux-toolkit

高级优化点:

  • 切 store(按域拆分)
  • selector 精准订阅
  • 避免顶层大对象

2️⃣ useReducer 实战场景

适合:

  • 多字段联动表单
  • 状态机流程
  • 复杂业务逻辑

示例:

js
const [state, dispatch] = useReducer(reducer, initialState)

优势:

  • 状态集中
  • 可测试
  • 可追踪

面试亮点:

用 useReducer 做过轻量状态机

二、副作用管理最佳实践

3️⃣ 请求封装:useRequest 模式

不要直接在组件里写 fetch。

推荐结构:

js
function useRequest(service, options) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(false)
  const abortRef = useRef(null)

  const run = useCallback(async (...args) => {
    abortRef.current?.abort()
    const controller = new AbortController()
    abortRef.current = controller

    setLoading(true)
    const result = await service(...args, controller.signal)
    setData(result)
    setLoading(false)
  }, [service])

  useEffect(() => {
    return () => abortRef.current?.abort()
  }, [])

  return { data, loading, run }
}

实战点:

  • 支持取消请求
  • 支持重复调用
  • 防止内存泄漏
  • 保证引用稳定

4️⃣ 流式输出场景(AI Chat)

你最近在准备 AI Chat 架构,这个很关键。

核心问题:

  • 流式更新会导致频繁 re-render
  • 长对话会卡顿
  • 需要可中断

优化方案:

  • useRef 存缓存
  • RAF 合并更新
  • useTransition 降低优先级
  • 消息分层 memo

三、性能优化实战

5️⃣ useMemo / useCallback 正确使用方式

❌ 常见错误

  • 到处包 useCallback
  • deps 填不对
  • 为优化而优化

✅ 正确使用场景

  • 传给 React.memo 子组件
  • 作为 useEffect 依赖
  • 大计算

6️⃣ 大列表优化

场景:2000 条消息

实战组合:

  • 虚拟列表
  • 消息组件 React.memo
  • key 稳定
  • 状态拆分(不要 messages 整体替换)

错误示例:

js
setMessages([...messages, newMsg])

优化:

  • 使用函数式更新
  • 拆成 map + id 存储

四、闭包问题实战解决方案

7️⃣ 定时器 Hook 封装

错误写法:

js
setInterval(() => console.log(count), 1000)

正确封装:

js
function useInterval(callback, delay) {
  const savedCallback = useRef(callback)

  useEffect(() => {
    savedCallback.current = callback
  })

  useEffect(() => {
    const id = setInterval(() => {
      savedCallback.current()
    }, delay)
    return () => clearInterval(id)
  }, [delay])
}

优点:

  • 永远拿最新 state
  • 不重新注册 interval

五、Context 高级用法

8️⃣ 避免全量刷新

问题:

Context value 改变 → 全部子组件重渲染

解决:

  • 拆分多个 context
  • useMemo 包裹 value
  • selector 模式

六、并发特性实战

9️⃣ useTransition 场景

搜索过滤:

js
const [isPending, startTransition] = useTransition()

const onSearch = (value) => {
  setInput(value)

  startTransition(() => {
    setFilteredList(filter(value))
  })
}

效果:

  • 输入不卡顿
  • 过滤低优先级

🔟 useDeferredValue 场景

用于:

  • 大表格
  • 数据图

与 useMemo 区别:

  • useMemo 是缓存
  • useDeferredValue 是调度延迟

七、Hooks 设计规范(团队级)

1️⃣1️⃣ 自定义 Hook 设计原则

  • 命名 useXxx
  • 单一职责
  • 不暴露内部状态结构
  • 返回对象结构稳定

推荐:

js
return useMemo(() => ({
  data,
  loading,
  run
}), [data, loading, run])

1️⃣2️⃣ 依赖数组规范

原则:

  • 不要忽略 ESLint 提示
  • 不要随便加 eslint-disable
  • 不要把对象写进 deps(除非 memo)

八、企业级最佳实践总结

状态设计

  • 状态最小化
  • 数据归一化
  • 拆分粒度

副作用设计

  • 所有副作用必须可清理
  • 必须考虑组件卸载
  • 请求必须可取消

性能设计

  • 默认不过度优化
  • 关键路径优化
  • 用 profiler 验证

九、高级前端面试总结

在 React 项目中,我通常遵循状态就近原则,用 useReducer 处理复杂逻辑,用自定义 Hook 封装副作用,并结合 useTransition 优化长列表或搜索场景。对闭包问题和并发渲染机制有深入理解,能在高频更新场景下保持 UI 流畅。

十、如果你是做 AI Chat / 大型系统

  • 流式渲染 Hook 设计
  • 可中断机制
  • 并发优先级控制
  • 虚拟列表
  • 状态分层