[英]React Hooks, setState not working with an async .map call
So, I'm trying to change a state in my component by getting a list of users to call an api.get to get data from these users and add on an new array with the following code:因此,我试图通过获取用户列表来调用 api.get 从这些用户获取数据并使用以下代码添加新数组来更改我的组件中的 state:
function MembersList(props) {
const [membersList, setMembersList] = useState(props.members);
const [devs, setDevs] = useState([]);
useEffect(() => {
let arr = membersList.map((dev) => {
return dev.login;
});
handleDevs(arr);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [membersList]);
function handleDevs(membersArr) {
membersArr.map(async (dev) => {
let { data } = await api.get(`/users/${dev}`);
/** If i console.log data here i actualy get the data from the user
but i think theres something wrong with that setDevs([...devs, data]) call
**/
setDevs([...devs, data]);
});
}
but the devs
state always return an empty array, what can I do to get it to have the actual users data on it?但是
devs
人员 state 总是返回一个空数组,我该怎么做才能让它拥有实际的用户数据?
You need to understand how React works behind scenes.你需要了解 React 是如何在幕后工作的。
In short, it saves all the "sets" until it finishes the cycle and just after that actually update each state.简而言之,它会保存所有“集合”,直到完成循环,然后才实际更新每个 state。
I think that why you do not see the current state updated.我想这就是为什么你没有看到当前 state 更新的原因。
For better understanding read this post: Medium article为了更好地理解这篇文章: Medium article
The issue is that setDevs
uses devs
which is the version of devs
when handleDevs
is defined.问题是
setDevs
使用devs
,这是定义handleDevs
时的devs
版本。 Therefore setDevs
will really only incorporate the data from the last time setDevs
is called.因此
setDevs
实际上只会合并上次调用setDevs
的数据。
To fix this you can use the callback version of setDevs
, like so:要解决此问题,您可以使用
setDevs
的回调版本,如下所示:
setDevs(prevDevs => [...prevDevs, data])
Also since you are not trying to create a new array, using map
is not semantically the best loop choice.此外,由于您没有尝试创建新数组,因此使用
map
在语义上并不是最佳循环选择。 Consider using a regular for
loop or a forEach
loop instead.考虑改用常规
for
循环或forEach
循环。
The issue you were having is because you were setting devs based on the data from the original render every time due to the closure around handleDevs function.您遇到的问题是,由于handleDevs function 周围的关闭,您每次都根据原始渲染中的数据设置开发人员。 I believe this should help take care of the issues you were having by using the callback method of using setDevs.
我相信这应该有助于通过使用 setDevs 的回调方法来解决您遇到的问题。 This also takes care of some issues with the dependency arrays and staleness in the useEffect hook.
这也解决了依赖 arrays 和 useEffect 挂钩中的一些问题。 Typically using
// eslint-disable-next-line react-hooks/exhaustive-deps
should be your last resort.通常使用
// eslint-disable-next-line react-hooks/exhaustive-deps
应该是你最后的手段。
function MembersList(props) {
// this isn't needed unless you are using it separately
const [membersList, setMembersList] = useState(props.members);
const [devs, setDevs] = useState([]);
useEffect(() => {
let arr = membersList.map((dev) => dev.login);
arr.forEach(async (dev) => {
let { data } = await api.get(`/users/${dev}`);
setDevs((devs) => [...devs, data]);
})
}, [membersList]);
}
you call setDevs
in the async execution loop.您在异步执行循环中调用
setDevs
。 Here is the updated handleDevs
function.这是更新的
handleDevs
function。
function handleDevs(membersArr) {
const arr = membersArr.map(async (dev) => {
let { data } = await api.get(`/users/${dev}`);
return data;
/** If i console.log data here i actualy get the data from the user
but i think theres something wrong with that setDevs([...devs, data]) call
**/
});
setDevs([...devs, ...arr]);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.