【问题标题】:Is there a difference between storing a const value in a variable vs in state?将 const 值存储在变量和状态之间有区别吗?
【发布时间】:2020-07-04 00:26:01
【问题描述】:

我注意到在 React 函数式组件中实现看似相同的事情的几种方法。当您拥有本质上是仅在此组件内部需要的配置值时(只是一个常量值,从未传入或修改)您可以只使用常规 const 或者您可以将其存储在组件的状态中。

标准变量:

function Example1() {
  const a = 1
  return <div>{ a }</div>
}

存储状态:

function Example2() {
  const [a] = useState(1)
  return <div>{ a }</div>
}

我的印象是,在幕后这会导致 Example1 在每次渲染上创建一个变量然后将其处理掉,而 Example2 将创建一次变量并保持它直到组件被卸载。那准确吗?就性能/良好做法而言,这些方法中的哪一种更可取?

【问题讨论】:

    标签: javascript reactjs react-hooks react-functional-component


    【解决方案1】:

    准确吗?

    是的,正如你所说,Example1 在每个渲染上创建一个变量(在范围末尾将其标记为“一次性” - 与 React 无关,但与 Javascript 无关),Example2 一次创建变量并维护它,直到组件被卸载(或此变量的状态通过setState 更改)。

    就性能/良好实践而言,这些方法中的哪一种更可取?

    作为一种良好做法 - 示例 1

    至于性能,应该是Example1Example2 运行 useState 并将值 a 与每次渲染上的先前状态进行比较,这比声明变量“昂贵得多”。

    比较组件参考/memoized变量与变量(Example1):

    function Example2() {
      const a = useRef(1);
      const b = useMemo(() => 1, []);
      return <div>{a.current} , {b}</div>
    }
    

    但答案几乎是一样的。

    看到这样的代码表明 ref a 可能会改变。使用useMemo表示b是一个“重计算”变量,如果不是,那只是一个开销(解释同上),最好使用示例1.

    【讨论】:

    • 这里什么被认为是繁重的计算?例如,如果变量的值是通过将一个 prop 传递给一个函数来计算的,该函数切换该 prop 然后返回一个值,它是否被认为是繁重的计算?如果没有,你能举个例子吗?
    • 繁重的计算是指在没有记忆的情况下出现渲染延迟。
    【解决方案2】:

    将此答案的重点放在何时使用什么。

    基本概念,

    • 如果您需要观察一个值并对其做出反应,将其存储在 state 中是有意义的。
    • 如果您只是想存储一个值用于显示/计算目的,使用const/let 更合适。

    现在是你的第二个例子

    const [a] = useState(1)
    

    这行代码是完全错误的。那是因为你正在添加一个观察者,但不接受 setter 回调。


    Example1 在每次渲染时创建一个变量

    是的,这是正确的。在 Example2 中,它创建了 1 个变量,但是,React 中的状态是不可变的。这意味着,每次渲染,整个对象都会被复制到一个临时变量,销毁并再次创建。由于这个事实,建议不要在状态中存储巨大的对象,因为这会对您的性能产​​生不利影响。

    【讨论】:

    • 嗯,很有趣。当您说 Example2 是错误的时,这纯粹是从“这是毫无意义的,因为它从未被修改过”的角度来看,还是它实际上会导致任何问题?我发现该示例的代码功能齐全且按预期工作,所以我的印象是有效的(这让我首先提出这个问题,想知道它是否比const I之前使用过)
    • @DBS 技术上没有错。但是当你为 state 添加值时,react 会为你提供一个 setter 并在这个变量上放置一个 watcher。如果你不接受 setter/使用它,你就是在浪费资源。此外,状态是 React 生命周期的一部分。如果变量具有静态值,我的建议是在配置​​或外部组件中定义它,因此不会创建额外的变量。但是放入状态是一种概念上不正确的地方
    • 你说:“React 中的状态是不可变的。这意味着,每次渲染,整个对象都会复制到一个临时变量,销毁并再次创建。”为什么呢?状态是不可变的这一事实如何使得对象在每次渲染时都被复制、销毁和创建?也许你可以给我指出一个这样说的文档
    【解决方案3】:

    您的假设几乎是正确的,useState 变量只创建一次并在每次渲染时重复使用。

    但是,主要区别在于修改使用 useState 创建的变量(通过其 setter 方法)会触发组件刷新。

    如果你只需要在渲染之间保存一个值,你应该使用其他钩子,例如useRef、useCallback 或 useMemo

    【讨论】:

      猜你喜欢
      • 2013-04-23
      • 2015-11-21
      • 2010-09-29
      • 1970-01-01
      • 2011-02-25
      • 2014-06-25
      • 1970-01-01
      • 2012-05-14
      • 1970-01-01
      相关资源
      最近更新 更多