useEffect 缺少依赖项,但是当我添加它时出现 'maximum update depth exceeded' 错误
useEffect is missing a dependency, but when I add it I get a 'maximum update depth exceeded' error
我正在尝试使用 hooks 解决问题,但我 运行 陷入了一个重复的问题。在下面链接的示例中,我有一个用于对数组进行排序的 useEffect 挂钩。排序顺序由状态值决定,我有一个切换该状态值的按钮。
一切都按照我的预期进行,当组件安装时数组被排序,然后点击按钮。
但是,我从 linter 中收到一个错误,需要将值数组声明为 useEffect 挂钩中的依赖项。如果这样做,我会收到 'Maximum update depth exceeded' 错误。我不确定该怎么做,如果有任何帮助,我将不胜感激!
感谢您的浏览,这对我来说意义重大!
我没有发现您的代码有任何问题。我要做的就是通过添加 // eslint-disable-next-line react-hooks/exhaustive-deps
来忽略警告,如下所示:
useEffect(() => {
function sortValues() {
let sorted;
const array = [...values];
if (ascValue) {
sorted = array.sort((a, b) => a - b);
} else {
sorted = array.sort((a, b) => b - a);
}
setValues(sorted);
}
sortValues();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ascValue]);
也许 sortValues()
上的一个缩短:
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
希望对您有所帮助!
理想情况下,您可以添加一些 condition/check 以查看 values
是否已经具有您想要的值。由于 setValues
似乎在每次渲染时都会被调用,这会触发重新渲染,乘以无穷大。
潜在地,使用像 Lodash 的 isEqual combined with Lodash's orderBy 这样的东西可以做到这一点(因为排序会改变原始数组)。
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState([
{ id: 10 },
{ id: 5 },
{ id: 12 },
{ id: 1 },
{ id: 2 },
{ id: 900 },
{ id: 602 }
]);
useEffect(() => {
function sortValues() {
const sorter = ascValue ? "asc" : "desc";
if (!_.isEqual(values, _.orderBy(values, ["id"], [sorter]))) {
console.log("logged");
setValues(() => _.orderBy(values, ["id"], [sorter]));
}
}
sortValues();
}, [ascValue, values]);
重点是,默认情况下,useEffect 不应该在每次渲染时都设置状态(它可以在渲染完成并且用户触发操作后设置)。
A fork of your CodeSandbox to demonstrate 如果满足条件,副作用应该只更新组件状态。
这并不奇怪 - 当您在依赖数组中添加值列表时,useEffect 将在值列表的每次更改时执行 - 这会导致无限循环:)
根据@norbitrial 之前的回答,隐藏错误不会解决问题,因为作用域中的每个依赖项都必须在依赖项数组中声明,避免它会导致意外行为。
我建议在这种情况下考虑使用 useReducer
。这将导致依赖项数组的修改逻辑可以移出 useEffect
挂钩的范围 - 并且您不会被迫将其附加为 useEffect
.
的依赖项
我正在尝试使用 hooks 解决问题,但我 运行 陷入了一个重复的问题。在下面链接的示例中,我有一个用于对数组进行排序的 useEffect 挂钩。排序顺序由状态值决定,我有一个切换该状态值的按钮。
一切都按照我的预期进行,当组件安装时数组被排序,然后点击按钮。
但是,我从 linter 中收到一个错误,需要将值数组声明为 useEffect 挂钩中的依赖项。如果这样做,我会收到 'Maximum update depth exceeded' 错误。我不确定该怎么做,如果有任何帮助,我将不胜感激!
感谢您的浏览,这对我来说意义重大!
我没有发现您的代码有任何问题。我要做的就是通过添加 // eslint-disable-next-line react-hooks/exhaustive-deps
来忽略警告,如下所示:
useEffect(() => {
function sortValues() {
let sorted;
const array = [...values];
if (ascValue) {
sorted = array.sort((a, b) => a - b);
} else {
sorted = array.sort((a, b) => b - a);
}
setValues(sorted);
}
sortValues();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ascValue]);
也许 sortValues()
上的一个缩短:
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
希望对您有所帮助!
理想情况下,您可以添加一些 condition/check 以查看 values
是否已经具有您想要的值。由于 setValues
似乎在每次渲染时都会被调用,这会触发重新渲染,乘以无穷大。
潜在地,使用像 Lodash 的 isEqual combined with Lodash's orderBy 这样的东西可以做到这一点(因为排序会改变原始数组)。
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState([
{ id: 10 },
{ id: 5 },
{ id: 12 },
{ id: 1 },
{ id: 2 },
{ id: 900 },
{ id: 602 }
]);
useEffect(() => {
function sortValues() {
const sorter = ascValue ? "asc" : "desc";
if (!_.isEqual(values, _.orderBy(values, ["id"], [sorter]))) {
console.log("logged");
setValues(() => _.orderBy(values, ["id"], [sorter]));
}
}
sortValues();
}, [ascValue, values]);
重点是,默认情况下,useEffect 不应该在每次渲染时都设置状态(它可以在渲染完成并且用户触发操作后设置)。
A fork of your CodeSandbox to demonstrate 如果满足条件,副作用应该只更新组件状态。
这并不奇怪 - 当您在依赖数组中添加值列表时,useEffect 将在值列表的每次更改时执行 - 这会导致无限循环:)
根据@norbitrial 之前的回答,隐藏错误不会解决问题,因为作用域中的每个依赖项都必须在依赖项数组中声明,避免它会导致意外行为。
我建议在这种情况下考虑使用 useReducer
。这将导致依赖项数组的修改逻辑可以移出 useEffect
挂钩的范围 - 并且您不会被迫将其附加为 useEffect
.