我正在发送这样一个请求:
function getDecks() {
return Axious.get(urlGetAllDecks).then((response) => response.data);
}
然后我使用一个函数式组件,我尝试通过从我的database.js文件中调用上述函数来初始化状态。然而,useEffect块被调用了无数次。
export interface DeckSelectionState {
id: number;
module: number;
title: string;
description: string;
dateCreated: string;
reviewStatus: number;
nextReviewDate: string;
}
const DeckSelection: React.FunctionComponent = () => {
const [decks, setDecks] = React.useState<DeckSelectionState[]>([]);
React.useEffect(() => {
database.getDecks().then((response) => {
setDecks(response);
});
});
有什么办法解决这个问题吗?
为了确保useEffect
只执行一次,你必须通过传递一个空数组来指定一个空的依赖列表。
代码应该如下所示:
React.useEffect(() => {
database.getDecks().then((response) => {
setDecks(response);
});
}, []);
useEffect
的第二个参数是依赖数组,它指定了效果所依赖的值的列表,这意味着只有当这些值中的一个改变时,效果才会执行。通过指定数组[]
,你基本上是说效果不依赖于任何值,应该只执行一次,而不指定依赖数组意味着效果依赖于所有道具和状态。
来自文档:
如果你想运行一个效果并且只清理一次(在挂载和卸载时),你可以传递一个空数组([])作为第二个参数。这告诉React你的效果不依赖于props或state的任何值,所以它永远不需要重新运行。这不是作为特殊情况处理的——它直接遵循依赖项数组的工作方式。如果你传递一个空数组([]),效果中的道具和状态将始终具有它们的初始值。虽然传递[]作为第二个参数更接近于熟悉的componentDidMount和componentWillUnmount心智模型,但通常有更好的解决方案来避免过于频繁地重复运行效果。另外,不要忘记React会在浏览器绘制完成之后才运行useEffect,所以做额外的工作不是什么问题。
为什么不指定[setDecks]
作为依赖数组?
setDecks
是用于设置与您使用的useState钩子相对应的状态的函数。虽然您可以将其添加到依赖数组中,但效果似乎"依赖";在它上面,它永远不会改变,因此它永远不会影响效果。来自useState
的文档:
React保证setState函数身份是稳定的,不会在重新渲染时改变。这就是为什么从useEffect或useCallback依赖列表中省略它是安全的。