为什么 'useState' 钩子在函数引用时会调用初始状态?



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

钩子 API 参考指出:

使用状态

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

返回一个有状态值和一个用于更新它的函数。

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

setState函数用于更新状态。它接受新的状态值,并将组件的重新呈现排队。

React 文档指出:

我们传递给useState什么作为论据?

useState()Hook 的唯一参数是初始状态。与类不同,状态不必是对象。如果这就是我们所需要的,我们可以保留一个数字或字符串。在我们的示例中,我们只需要一个数字来表示用户点击的次数,因此0作为变量的初始状态传递。(如果我们想在 state 中存储两个不同的值,我们会调用useState()两次。

意外行为:

但是,我注意到一些奇怪的,似乎没有记录的行为。

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

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并使用它的返回值作为状态。

作为解决方法:

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

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

我还没有遇到任何将函数存储为状态的现实原因,但有人明确选择以不同的方式处理函数参数似乎很奇怪。

在整个 React 代码库中的多个位置都可以看到这个选择:

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

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

我想不出任何很好的理由为什么有人希望/期望调用他们的函数引用,但也许你可以。

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

此处记录了以下内容:

延迟初始状态

初始状态参数是初始呈现期间使用的状态。 在随后的渲染中,它被忽略。如果初始状态为 昂贵的计算结果,您可以提供一个函数 相反,这将仅在初始渲染上执行:

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

将回调传递给setState也会调用回调,但原因不同:

功能更新

如果使用以前的状态计算新状态,则可以传递 函数来设置状态。该函数将接收上一个值, 并返回更新的值。下面是计数器组件的示例 使用两种形式的 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>
</>
);
}

相关内容

  • 没有找到相关文章

最新更新