为什么需要 useRef 而不是可变变量? [英] Why need useRef and not mutable variable?

查看:40
本文介绍了为什么需要 useRef 而不是可变变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读

I have read A Complete Guide to useEffect - Swimming Against the Tide at Overreacted.

The example shows that if we want to get the latest count, we can use useRef to save the mutable variable, and get it in async function 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);
  });
  // ...
}

However, I can do the same thing by creating a variable outside the component function, such as:

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;

Are both ways practical, or is there anything bad if I define the variable outside function component?

解决方案

useRef will assign a reference for each component, while a variable defined outside a function component scope will only assigned once.

useRef reference life span is component's life span (it "dies" when the component unmounts, while JS variables are scope-blocked).

Hence, define constant purpose variables outside of the component scope:

// This statement will only called once
const DEFAULT_VALUE = 5;

function Component() {
  // use DEFAULT_VALUE.
}

Defining the same statement inside component's scope, will redefine it on every render:

// We can do better
function Component() {
  // Redefined on every render
  const DEFAULT_VALUE = 5;
}


Now for the question:

First, we can't actually reflect UI changed with outer scoped variables since changing them does not trigger render (only React API does).

Therefore the reflected value is its closure value.

let countCache = 0;

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

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

  // closure value of countCache
  return <div>{countCache}</div>
}


Now, whats special with outer scope variables that they are global to the module itself, so using its value is global to all components referencing it (in the module).

For example if you want to count how many times the component mounted in your whole application life span, increase the variable inside useEffect on mount (couldn't find any other possible use-case).

let howMuchMounted = 0;

function Component() {
  useEffect(() => { howMuchMounted += 1, [] };
}

To reflect the differences of outer variable and useRef reference, in the next example, on button click, you may notice that the variable is global for both of the components, while the reference is always updated to current state value.

import React, { useEffect, useRef, useReducer } from "react";
import ReactDOM from "react-dom";

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

function Counter() {
  const [num, count] = useReducer((num) => num + 1, 0);

  const countRef = useRef(count);

  useEffect(() => {
    // set count value on count change
    countCache = num;
    countRef.current = num;
  }, [num]);

  return (
    <>
      <button onClick={count}>Count</button>
      <h3>state {num}</h3>
      <h3>variable {countCache}</h3>
      <h3>reference {countRef.current}</h3>
    </>
  );
}

export default function App() {
  return (
    <>
      <Counter />
      <hr />
      See what happens when you click on the other counter
      <hr />
      <Counter />
    </>
  );
}


Please see a follow up question on useEffect use cases, there are many common mistakes when working with useRef references inside useEffect.

这篇关于为什么需要 useRef 而不是可变变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆