为什么需要useRef在组件函数之外包含可变变量而不定义变量?

PJC*_*der 2 reactjs react-hooks

我已阅读了《使用效果的完全指南-过度反应应对潮流》

该示例表明,如果我们想获取最新的count,我们可以useRef用来保存可变变量,并在异步函数laster中获取它:

function Example() {
  const [count, setCount] = useState(0);
  const latestCount = useRef(count);

  useEffect(() => {
    // Set the mutable latest value
    latestCount.current = count;
    setTimeout(() => {
      // Read the mutable latest value
      console.log(`You clicked ${latestCount.current} times`);
    }, 3000);
  });
  // ...
}
Run Code Online (Sandbox Code Playgroud)

但是,我可以通过在组件函数外部创建一个变量来执行相同的操作,例如:

import React, { useState, useEffect, useRef } from 'react';

// defined a variable outside function component
let countCache = 0;

function Counter() {
  const [count, setCount] = useState(0);
  countCache = count;       // set default value

  useEffect(() => {
    setTimeout(() => {
      // We can get the latest count here
      console.log(`You clicked ${countCache} times (countCache)`);
    }, 3000);
  });
  // ...
}

export default Counter;
Run Code Online (Sandbox Code Playgroud)

两种方法都可行,或者如果我在函数组件外部定义变量,有什么不好的方法吗?

KJ *_*han 20

以下四种可能的变体之间存在差异:

  1. 函数组件内部的变量
  2. 函数组件外部的变量
  3. useState() 返回的状态变量
  4. useRef() 返回的变量(具有属性“current”的对象)

最后 2 个只能在组件内使用。


让我们看一下每种情况:

1.函数组件内部的变量

Initialization:变量总是在每次渲染时以及因此在多个组件实例中重新初始化

Variable Updates: 可以更新,除了 const

Render:React 不会触发任何渲染,因此不会反映更新的值


2.函数组件外的变量

Initialization:变量仅在文件加载时初始化。并且该文件仅加载一次,无论有多少组件消耗该文件的导出。这是与使用 useRef() 相比的主要区别。如果只有一个组件实例化,则与 useRef() 相同。

Variable updates: 可以更新,除了 const

Render:React 不会触发任何渲染,因此不会反映更新的值


3. useState() 返回的状态变量

Initialization:变量仅在组件安装时初始化,与渲染次数无关。然而,每个组件实例都有它自己的状态变量副本。

Variable updates:可以使用状态更新器功能进行更新。

Render:状态变量更新后,React 会触发渲染(多个更新可能会批处理到单个渲染中)


4. useRef() 返回的变量(具有属性“current”的对象)

Initialization:变量仅在组件安装时初始化,与渲染次数无关。但是,这将为每个组件实例独立初始化变量,而在组件外部使用变量时仅发生一次

Variable updates:可以使用“当前”属性进行更新

Render:React 不会触发任何渲染,因此不会反映更新的值


选择上述任何一项在很大程度上取决于需求,但我们的工具箱中有必要的工具来覆盖几乎所有用例。

  • 我可能会把它打印出来贴在墙上。做得好。 (6认同)

Den*_*ash 7

useRef将为每个组件分配一个引用,而在函数组件外部定义的变量将仅被调用一次。

此外,尝试呈现该countCache值将行不通:

let countCache = 0;

function Counter() {
  ...
  countCache = 0;

  useEffect(() => {
    countCache = count;
  });
  ...

  return <div>{countCache}</div>
}
Run Code Online (Sandbox Code Playgroud)

由于使用了javascript闭包,因此参考可以按方面使用。

在下一个示例中,单击按钮时,您可能会注意到variable两个组件都是全局的,而reference总是按预期更新。

// defined a variable outside function component
let countCache = 0;

function Counter() {
  const [count, setCount] = useState(0);

  const countRef = useRef(count);

  useEffect(() => {
    // Update count on every render
    countCache = count;
    countRef.current = count;
  });

  return (
    <div>
      <button onClick={() => setCount(p => p + 1)}>click me</button>
      <h3>variable</h3>
      {countCache}
      <h3>reference</h3>
      {countRef.current}
    </div>
  );
}

export default function App() {
  return (
    <FlexBox>
      <FlexBox>
        <Counter />
      </FlexBox>
      <FlexBox>
        <Counter />
      </FlexBox>
    </FlexBox>
  );
}
Run Code Online (Sandbox Code Playgroud)

编辑Q-57444154-封闭

  • 我发现这个答案只是解释了全局变量与局部变量的基本差异。每当组件死亡时,其局部作用域变量也随之死亡。当您有一个文件托管所有微小的相关组件时,全局变量非常有用,这些组件引用一些共享变量,例如按钮主题、翻译、基于颜色的设备等,因为当这些微小的任何一个时,全局变量不会消失或重新初始化组件重新渲染。 (2认同)

归档时间:

查看次数:

139 次

最近记录:

5 年,10 月 前