为什么当'useState'钩子是函数引用时,它会调用初始状态? [英] Why does the 'useState' hook invoke the initial state when it's a function reference?

查看:271
本文介绍了为什么当'useState'钩子是函数引用时,它会调用初始状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

React有一个名为 useState 的钩子,该钩子在向其中添加状态时使用功能组件.

React has a hook called useState, which is used when adding state to functional components.

useState :

const [state, setState] = useState(initialState);

返回一个有状态值,以及一个更新它的函数.

Returns a stateful value, and a function to update it.

在初始渲染期间,返回的状态( state )与作为第一个参数( initialState )传递的值相同.

During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState).

setState 函数用于更新状态.它接受一个新的状态值并排队重新呈现该组件.

The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.

反应文档指出:

我们将什么作为参数传递给 useState ?

What do we pass to useState as an argument?

useState()挂钩的唯一参数是初始状态.与类不同,状态不必是对象.如果需要,我们可以保留一个数字或一个字符串.在我们的示例中,我们只需要一个用户点击次数的数字,因此将 0 用作变量的初始状态.(如果我们想在状态中存储两个不同的值,我们将调用两次 useState().)

The only argument to the useState() Hook is the initial state. Unlike with classes, the state doesn’t have to be an object. We can keep a number or a string if that’s all we need. In our example, we just want a number for how many times the user clicked, so pass 0 as initial state for our variable. (If we wanted to store two different values in state, we would call useState()twice.)

意外行为:

但是,我注意到一些奇怪的,看似没有记载的行为.

如果我尝试使用 useState 钩子将函数存储为状态,则 react将调用函数引用.例如

If I try to use the useState hook to store a function as state, react will invoke the function reference. e.g.

const arbitraryFunction = () => {
    console.log("I have been invoked!");
    return 100;
};

const MyComponent = () => {

    // Trying to store a string - works as expected:
    const [website, setWebsite] = useState("stackoverflow"); // Stores the string
    console.log(typeof website);                             // Prints "string"
    console.log(website);                                    // Prints "stackoverflow"

    // Trying to store a function - doesn't work as expected:
    const [fn, setFn] = useState(arbitraryFunction);         // Prints "I have been invoked!"
    console.log(typeof fn);                                  // Prints "number" (expecting "function")
    console.log(fn);                                         // Prints "100"

    return null; // Don't need to render anything for this example...
};

当我们调用 useState(arbitraryFunction)时,react将调用 arbitraryFunction 并将其返回值用作状态.

When we call useState(arbitraryFunction), react will invoke arbitraryFunction and use its return value as the state.

我们可以通过将函数引用包装在另一个函数中来将函数存储为状态.例如

We can store functions as state by wrapping our function reference in another function. e.g.

const [fn, setFn] = useState(() => arbitraryFunction)

我还没有遇到任何现实的理由将函数存储为状态,但是似乎很奇怪,有人做出了明确的选择以不同的方式对待函数参数.

I haven't yet come across any real-world reasons to store functions as state, but it seems weird that somebody made the explicit choice to treat function arguments differently.

在整个反应代码库中的多个地方都可以看到这种选择:

This choice can be seen in multiple places throughout the React codebase:

initialState = typeof initialArg === 'function' ? initialArg() : initialArg;

为什么这个看似未记录的功能存在?

我想不出为什么有人希望/期望调用他们的函数引用的任何充分理由,但是也许可以.

Why does this seemingly undocumented feature exist?

I can't think of any good reasons why anybody would want/expect their function reference to be invoked, but perhaps you can.

如果已记录,在哪里记录?

If this is documented, where is it documented?

推荐答案

惰性初始状态

initialState参数是在初始渲染期间使用的状态.在后续渲染中,将忽略它.如果初始状态是昂贵的计算结果,您可以提供一个函数而是仅在初始渲染上执行:

Lazy initial state

The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render:

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

将回调传递给 setState 也会调用该回调,但出于其他原因:

功能更新

如果新状态是使用先前状态计算的,则可以传递一个函数为setState.该函数将接收先前的值,并返回更新的值.这是计数器组件的示例使用两种形式的setState:

Functional updates

If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value. Here’s an example of a counter component that uses both forms of setState:

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

这篇关于为什么当'useState'钩子是函数引用时,它会调用初始状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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