![](/img/trans.png)
[英]React setState inside componentDidUpdate causing infinite loop
[英]Why is my setState causing an infinite loop?
我有一些代码从firebase数据库中获取用户列表,将其随机化,然后返回一个-但是,当我尝试将状态设置为随机选择的用户时,我遇到了无限循环。
我尝试过将setState()在现在的位置和randomizeUsers函数之间移动,但得到的结果相同
有问题的代码:
const [state, setState] = useState({
potentialParnter: null
});
useEffect(() => {
generateRandomPotentialPartner();
console.log(state.potentialParnter)
})
const getUsers = () => {
const database = firebase.database()
const users = database.ref('users');
return new Promise((resolve, reject) => {
try {
users.on('value', function(snapshot) {
const users = []
snapshot.forEach(function(childSnapshot) {
let user = childSnapshot.val();
users.push(user)
});
resolve(users);
});
} catch(e) {
reject(e);
}
})
}
async function generateRandomPotentialPartner() {
try {
const users = await getUsers();
const randomUser = randomizeUsers(users)
setState({
potentialParnter: randomUser
})
} catch (error) {
console.log(error)
}
}
const randomizeUsers = (users) => {
const randomPotentialParnter = users[Math.floor((Math.random() * users.length))]
return randomPotentialParnter
}
const potentialParnter = state.potentialParnter ? state.potentialParnter.name : 'loading'
这是因为您的useEffect()
挂钩。 每当组件的状态或道具更新时,都会触发useEffect()
挂钩。 有点像componentDidUpdate()
。
由于您正在执行一些逻辑来更新useEffect
的状态,因此只会创建一个无限循环。
您可以通过将一个空数组作为第二个参数添加到useEffect()
来避免这种情况。 使它实际上与componentDidMount()
相同。 因此,其中的逻辑只会运行一次。
useEffect(() => {
generateRandomPotentialPartner();
console.log(state.potentialParnter)
}, [])
这是因为useEffect
:如果不提供第二个参数,则此挂钩将在每次组件重新渲染时运行。
因此,您的代码中发生的情况如下:
如果您希望它仅在安装组件时运行,请提供一个空数组作为第二个参数:
useEffect(() => {
generateRandomPotentialPartner();
console.log(state.potentialParnter)
}, []);
您应该向useEffect
添加一个空的依赖项数组,以防止其循环:
useEffect(() => {
generateRandomPotentialPartner();
}, []);
如果要记录state
更改时的state
结果,则可能需要另一个useEffect
:
useEffect(() => {
console.log(state.potentialParnter);
}, [state]);
改变这个
const [state, setState] = useState({
potentialParnter: null
});
为此(以便我们稍后可以检查其长度以使用该长度来知道是否重新渲染)
const [state, setState] = useState({
potentialParnter: ""
});
====================================
然后改变这个
useEffect(() => {
generateRandomPotentialPartner();
console.log(state.potentialParnter)
})
为此(现在我们正在检查其长度是否已更改,然后我们可以重新渲染,否则我们将不重新渲染)
useEffect(() => {
generateRandomPotentialPartner();
console.log(state.potentialParnter)
}, [state.potentialParnter.length])
=======================================
然后改变这个
try {
const users = await getUsers();
const randomUser = randomizeUsers(users)
setState({
potentialParnter: randomUser
})
} catch (error) {
console.log(error)
}
为此(假设您只希望世代发生一次)
try {
const users = await getUsers();
const randomUser = randomizeUsers(users)
if(state.potentialPartner.length == 0){
setState({
potentialParnter: randomUser
})
}
} catch (error) {
console.log(error)
}
希望这对您有用。 我对其他答案的解释基于相同的原理,因此无需重复解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.