在 useEffect 中处理 forEach 后调用 setstate
Posted
技术标签:
【中文标题】在 useEffect 中处理 forEach 后调用 setstate【英文标题】:Calling setstate after processing forEach within useEffect 【发布时间】:2021-09-22 21:16:20 【问题描述】:我正在尝试在 useEffect 上处理一些 api 数据,在处理数据时我需要将其设置为各种状态,在处理数据时,由于某些原因 useEffect 被无限触发。尽管从类组件中我知道 setState 是一个不等待 forEach 完成的异步操作。我们有针对功能组件的解决方法吗?
useEffect(() =>
const apiResponse = fetchAppName();
apiResponse.then(
(response) =>
// if (response.statusCode === '200' && response.status.statusType === 'SUCCESS' && response.data)
const dataFields = ;
const appNameValues = [];
dummyData.data.forEach((ele) =>
const workFlowIds = [];
ele.workflowConfigs.forEach((wc) =>
workFlowIds.push(wc.workflowId);
)
dataFields[ele.name] = workFlowIds;
);
Object.keys(dataFields).forEach((k) =>
appNameValues.push(k);
);
setAppData(dataFields);
setDropDownOptions(
...dropDownOptions,
appName: appNameValues,
);
//
).catch((e)=>
console.log('Failed to fetchAppNames due to: ', e);
);
,[setDropDownOptions, dropDownOptions]);
【问题讨论】:
不要把setter放在依赖数组中 即使在那之后它也被无限调用@Jazz 您希望效果何时运行? 你设置它,然后在设置它时调用它,所以它正在创建一个循环我认为你应该删除这两个依赖项 @DrewReese:我想在第一个 forEach 循环完成后运行这个效果,基本上在所有 forEach 完成时调用 setDropDownOptions 【参考方案1】:问题
不要使用由效果更新的依赖项。换句话说,dropDownOptions
是一个依赖,效果会更新它,从而创建一个渲染循环。
解决方案
状态更新函数是稳定的,所以没必要,用一个函数状态更新来移除另一个dropDownOptions
依赖。
useState
注意
React 保证 setState 函数的身份是稳定的,不会 更改重新渲染。这就是为什么从 useEffect 中省略是安全的 或者 useCallback 依赖列表。
useEffect(() =>
const apiResponse = fetchAppName();
apiResponse.then(
(response) =>
// if (response.statusCode === '200' && response.status.statusType === 'SUCCESS' && response.data)
const dataFields = ;
const appNameValues = [];
dummyData.data.forEach((ele) =>
const workFlowIds = [];
ele.workflowConfigs.forEach((wc) =>
workFlowIds.push(wc.workflowId);
)
dataFields[ele.name] = workFlowIds;
);
Object.keys(dataFields).forEach((k) =>
appNameValues.push(k);
);
setAppData(dataFields);
setDropDownOptions(dropDownOptions => (
...dropDownOptions,
appName: appNameValues,
));
//
).catch((e)=>
console.log('Failed to fetchAppNames due to: ', e);
);
,[]); // will run on mount, add other dependency triggers if needed.
【讨论】:
我曾经在某处读到 setState 和 forEach 循环一样是异步的。我有点想,也许在第一次 forEach 的执行过程中调用了 setDropDownOptions,然后再一次 forEach 循环继续执行剩下的上下文,从而形成了一个渲染循环。 @DrewResse @AshishBairwasetState
和 useState
更新函数是完全同步的函数,它们将要更新的状态排入队列(即“请求”)。 React 排队状态更新异步处理。 forEach 循环也是同步的。
@DrewResse github.com/facebook/react/issues/11527#issuecomment-360199710以上是关于在 useEffect 中处理 forEach 后调用 setstate的主要内容,如果未能解决你的问题,请参考以下文章
如何在 useEffect 挂钩中使用 Promise.all 获取所有数据?
在 ReactJS 的 useEffect 中定义后 useEffect 值保持不变
useState 在 useEffect 中定义后保持初始状态
React - 是不是在 useEffect 中调用 API