打破常识:React中Props更新并不意味着重渲染!- 从 useState 和 useRef 中看 react 更新机制

在React的世界里,有一个广泛流传的误解:每当组件的props发生变化,React就会自动触发重渲染。这种说法是不正确的,实际上,React的更新逻辑复杂,它涉及到一系列精妙的优化机制,这些机制决定了何时以及为何进行重渲染,但我们日常使用触发重渲染的事件只有一个,那就是 通过 setState 来更改 state 的。

接下来,就从 useState 和 useRef 中来看 React 更新机制。

在React中,useState useRef 都是React Hook,用于在函数组件中管理状态和引用。区别是 state 的变化会引起 React 的更新,ref 的变化不会。

下面就使用代码来解释这个情况

react 中页面更新实际上就是重新执行了一遍这个组件函数

在代码加了一行打印,你在自己实践的时候也可以观察一下。

import React, { useState, useRef } from "react";

const Children = ({ name, value }: { name: string; value: number }) => {
  // 每一次子组件更新时,都会触发
  console.log(name, ":", value, "render");
  return (
    <div>
      {name}-Children:{value}
    </div>
  );
};

const CounterWithRef = () => {
  // 使用 useState 来管理计数状态
  const [count, setCount] = useState(0);

  // 使用 useRef 来存储计数的持久性引用,不会导致重新渲染
  const countRef = useRef(0);

  // 每一次页面更新时,都会触发
  console.log("count:", count, "countRef.current:", countRef.current, "render");

  const handleAdd = () => {
    // 使用 useState 更新状态,并触发重新渲染
    setCount((prevCount) => prevCount + 1);
  };

  const handleRefAdd = () => {
    // 使用 useRef 直接更新引用,不触发重新渲染
    countRef.current = countRef.current + 1;
  };

  const handleCheck = () => {
    // 用于实时查看 useState 和 useRef 的值
    console.log(
      "count:",
      count,
      "countRef.current:",
      countRef.current,
      "check"
    );
  };

  return (
    <div>
      <div style={{ display: "flex", gap: "6px" }}>
        <p>Count (useState): {count}</p>
        <button type="button" onClick={handleAdd}>
          add
        </button>
      </div>
      <div style={{ display: "flex", gap: "6px" }}>
        <p>Count (useRef): {countRef.current}</p>
        <button onClick={handleRefAdd}>refAdd</button>
      </div>
      <div onClick={handleCheck}>check</div>
      <Children name="useState" value={count}></Children>
      <Children name="useRef" value={countRef.current}></Children>
    </div>
  );
};

export default CounterWithRef;

在代码中,我加入了check的按钮,你可以通过点击来实时查看 state 和 ref 的值。

  1. 每一次点击 add 都会触发页面更新,打印也会打印,而且 useState 的 Children 同步更新。
  2. 每一次点击 refAdd 页面不会更新,打印也没有打印,而且 useRef 的 Children 不会更新,点击check 可以看到 countRef.current 的值确实变化了。这也就证明了 props 的更新不会引起 react 的页面更新。
  3. 在点击 refAdd 后,再点击 add ,现象和 1 一样,而且打印的值都是最新的,2个子组件都更新。也就是说 state 的变化引起了整个组件的更新,所以误解就是在这里来的,实际上是因为你把父组件的 state 当子组件的 props 传递下去,而 state 的变化引起了整个组件的更新,子组件也跟着更新

最后再留个问题,每一次点击 add ,2个子组件的打印都会打印,但是 useRef 的子组件的 props 并没有更新, 理论上来说是不需要更新的。那么应该如何优化呢,使得点击 add 后只有 countRef.current 的值变了,countRef.current 的子组件才更新。

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值