react hook注意事项

写代码出错了,很少深入了解 hook。让ai给总结了一下。

这确实是 React 中非常核心且容易被忽视的"铁律"。React 的很多设计理念与传统的命令式编程(如 jQuery)或基于类的编程(Vue Options API)不太一样,因此有很多类似的"潜规则"和陷阱。

以下为您整理了 React 开发中必须知道的 6 个核心注意事项,掌握这些可以帮您避开 90% 的 Bug:

1. useEffect 依赖数组不能"撒谎" (Stale Closure / 闭包陷阱)

这是 Hook 最容易出 Bug 的地方。如果你在 useEffectuseCallback 内部使用了某个变量,但没有把它加到依赖数组 [] 中,Hook 内部就会一直引用旧的变量值

  • ❌ 错误写法:

    JavaScript 复制代码
    const [count, setCount] = useState(0);
    
    useEffect(() => {
      const timer = setInterval(() => {
        console.log(count); // 永远打印 0!因为这里的 count 是闭包捕获的初始值
      }, 1000);
      return () => clearInterval(timer);
    }, []); // 依赖数组是空的,导致 effect 只运行一次,内部永远拿着旧的 count
  • ✅ 正确写法:

    JavaScript 复制代码
    useEffect(() => {
      const timer = setInterval(() => {
        console.log(count);
      }, 1000);
      return () => clearInterval(timer);
    }, [count]); // 依赖 count,每次 count 变化,effect 会销毁旧的并重新运行

    或者使用函数式更新(如果不依赖外部变量触发 Effect):

    JavaScript 复制代码
    setCount(prevCount => prevCount + 1); // 这种写法不需要依赖 count

2. State 更新是"异步"的(快照特性)

调用 setState 后,状态不会立即改变。React 会把更新放入队列,等到下一次渲染时才会生效。

  • ❌ 常见误区:

    JavaScript 复制代码
    const handleClick = () => {
      setCount(count + 1);
      console.log(count); // 打印的仍然是旧值!不是 +1 后的值
    
      // 如果此时发请求,发出去的也是旧值
      fetchData(count); 
    };
  • ✅ 正确理解:

    如果你需要使用更新后的值,应该使用 useEffect 监听该值的变化,或者在 setState 中使用回调函数(仅用于计算新值)。

    JavaScript 复制代码
    useEffect(() => {
      console.log(count); // 这里才能拿到更新后的值
      fetchData(count);
    }, [count]);

3. 永远不要直接修改 State (Immutability / 不可变性)

React 比较状态是否变化是基于引用比较(Shallow Compare)。如果你直接修改对象属性,引用地址没变,React 就不知道数据变了,页面就不会刷新。

  • ❌ 错误写法:

    JavaScript 复制代码
    const [user, setUser] = useState({ name: 'Alice', age: 18 });
    
    const updateName = () => {
      user.name = 'Bob'; // 修改了内容,但对象引用没变
      setUser(user);     // React 认为前后是同一个对象,不触发重新渲染
    };
  • ✅ 正确写法:

    JavaScript 复制代码
    const updateName = () => {
      // 创建一个新对象(复制旧属性 + 覆盖新属性)
      setUser({ ...user, name: 'Bob' }); 
    };

4. 列表渲染必须有唯一的 key(且尽量不要用 index)

key 是 React 识别 DOM 节点的身份证。如果使用数组索引(index)作为 key,当列表顺序发生变化(插入、删除、排序)时,React 会复用错误的 DOM 节点,导致状态错乱。

  • ❌ 风险写法:

    JavaScript 复制代码
    // 如果列表顺序会变,千万别用 index
    {items.map((item, index) => <li key={index}>{item.name}</li>)}
  • ✅ 正确写法:

    JavaScript 复制代码
    // 使用数据中的唯一 ID
    {items.map((item) => <li key={item.id}>{item.name}</li>)}

5. useEffect 的清理函数 (Cleanup Function)

如果在 useEffect 中订阅了事件、设置了定时器或发起了请求,必须返回一个清理函数,否则会导致内存泄漏或逻辑错误(比如组件卸载了但定时器还在跑)。

  • ✅ 标准模板:

    JavaScript 复制代码
    useEffect(() => {
      // 1. 设置副作用
      const handleResize = () => console.log(window.innerWidth);
      window.addEventListener('resize', handleResize);
    
      // 2. 返回清理函数
      return () => {
        window.removeEventListener('resize', handleResize);
      };
    }, []);

6. React Strict Mode 下的"重复执行"

在开发环境(Development)中,为了帮你检查不纯的副作用,React 的 <StrictMode> 会故意将你的组件渲染两次useEffect 也会执行两次。

  • 现象 :你看控制台日志,发现 API 请求发了两次,或者 console.log 打印了两次。
  • 注意 :这不是 Bug,生产环境(Production)不会发生。不要为了解决这个问题去写奇怪的代码,而应该确保你的 Effect 是可以重复执行且无害的(做好清理工作)。

总结建议

您刚遇到的 "Hook 顺序与数量必须一致" 是 React 运行机制的物理限制(React 内部是靠数组索引来记录每个 Hook 的状态的,如果顺序乱了,状态就张冠李戴了)。

而上面提到的这 6 点,更多是逻辑和模式上的注意事项。掌握了这些,您写 React 就会非常有底气了。

相关推荐
红色石头本尊10 分钟前
1-umi-前端工程化搭建
前端
真夜17 分钟前
关于对echart盒子设置百分比读取的宽高没有撑开盒子解决方案
前端
楠木68531 分钟前
RAG 资料库 Demo 完整开发流程
前端·ai编程
肠胃炎42 分钟前
挂载方式部署项目
服务器·前端·nginx
像我这样帅的人丶你还1 小时前
使用 Next.js + Prisma + MySQL 开发全栈项目
前端
FPGA小迷弟1 小时前
FPGA 时序约束基础:从时钟定义到输入输出延迟的完整设置
前端·学习·fpga开发·verilog·fpga
毛骗导演1 小时前
@tencent-weixin/openclaw-weixin 插件深度解析(四):API 协议与数据流设计
前端·架构
毛骗导演1 小时前
@tencent-weixin/openclaw-weixin 插件深度解析(二):消息处理系统架构
前端·架构
IT_陈寒2 小时前
深入理解JavaScript:核心原理与最佳实践
前端·人工智能·后端
MrGud2 小时前
Cesium中的坐标系及其转换
前端·cesium