我无法解决下面的问题。
该问题与异步setState维度有关。通常我会使用回调,但这里似乎不合适。
我的目标是创建一个状态(我将能够排序),这是通过迭代自己在地图中创建的不同状态获得的。
下面的函数调用我的不同方法,我们感兴趣的方法是最后两个方法。 getUserPoints
和sortArrayforUserRank
。
getPlayersByUser = () => {
database
.ref(`pools/${this.state.selectedValue}`)
.once("value")
.then(data => {
for (let item in data.val()) {
this.setState({
users: this.state.users.concat([item])
});
this.setState({ [item]: data.val()[item] });
}
})
.then(this.makePlayersArray)
.then(this.getUserPoints)
.then(this.sortArrayforUserRank);
getUserPoints = () => {
this.state.users.map(user => {
// Create the dynamic name of the state, 1 for each user
let userPoints = `${user}points`;
// initializing the state for userPoint to be at 0 for future calculation
this.setState({ [userPoints]: 0 });
this.state[user].map(player => {
database
.ref(`players/${player}`)
.child("points")
.once("value")
.then(data => {
let points = parseInt(data.val());
this.setState(state => ({
[userPoints]: points + state[userPoints]
}));
});
});
});
getUserPoints
允许我动态创建state.userPoints,为每个用户总结玩家的所有积分。
然后我期待下面的sortArrayforUserRank
使用更新的state.userPoints来创建我的最终userArrayPoints状态。
sortArrayforUserRank = () => {
this.state.users.map(user => {
let userPoints = `${user}points`;
this.setState(state => ({
userArrayPoints: state.userArrayPoints.concat([
{ [user]: state[userPoints] }
])
}));
});
目前,userArrayPoints将填充4个对象{[user]:0}
,而不是每个用户的最终点数总和。问题是在前一个setState完成之前调用了sortArrayforUserRank
我本来喜欢在getUserPoints
中使用setState回调,但由于我在玩家地图功能中会为每个玩家调用它,而我想在用户lvl处理它以获得最终的积分总和。
我尝试使用componentDidUpdate
,并根据这些文章使用函数setState,但无法弄清楚。
https://medium.com/@shopsifter/using-a-function-in-setstate-instead-of-an-object-1f5cfd6e55d1
https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b
您的帮助将受到赞赏,
谢谢
答案 0 :(得分:1)
您无法使用setState
执行此处尝试的操作,因为它是异步的,并且会与该for ()
循环中每次迭代时可用的不同状态冲突。
你可以做的是首先提取状态,根据需要进行操作,然后运行setState
(至少在下面的这个中)
.then(data => {
// Pull out what you want to mess with here first
const users = [ ...this.state.users ];
const dataValObj = data.val();
// Then use spread operator (or Object.assign/Array.concat)
this.setState({
users: [
...users,
...Object.keys(dataValObj)
],
...dataValObj
});
})
似乎你在整个代码中遵循了类似的模式。尝试将我在这里所做的工作应用到其中使用setState
的循环的其他区域。
答案 1 :(得分:0)
使用下面的承诺找到了一种方法。它允许我从循环中删除setState并直接处理它而不必依赖于2 setstate。这两条评论/答案都帮助我处理了这个问题,
getUserPoints = () => {
this.state.users.map(user => {
// Create the dynamic name of the state, 1 for each user
let userPoints = `${user}points`;
// initializing the state for userPoint to be at 0 for future calculation
this.setState({ [userPoints]: 0 });
let userCounter = 0;
let promiseArrays = [];
this.state[user].map(player => {
let promise = database
.ref(`players/${player}`)
.child("points")
.once("value")
.then(data => {
let points = parseInt(data.val());
return (userCounter = userCounter + points);
});
promiseArrays.push(promise);
});
Promise.all(promiseArrays).then(() =>
this.setState({
userArrayPoints: this.state.userArrayPoints.concat({
[user]: userCounter
})
})
);
});
};
答案 2 :(得分:0)
只需在this.setState中使用第二个参数。
第二个参数是一个在设置状态后调用的函数。
this.setState({ 名称:值 },()=> {this.nameOfTheFunctionYouWantToRunNext()});