我有一些代码可以从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'
答案 0 :(得分:1)
这是因为您有useEffect()
钩。每当您更新组件的状态或道具时,都会触发useEffect()
挂钩。有点像componentDidUpdate()
。
由于您正在执行一些逻辑来更新useEffect
中的状态,所以这只会创建一个无限循环。
您可以通过向useEffect()
添加一个空数组作为第二个参数来避免这种情况。使其实际上与componentDidMount()
相同。因此,其中的逻辑只会运行一次。
useEffect(() => {
generateRandomPotentialPartner();
console.log(state.potentialParnter)
}, [])
答案 1 :(得分:1)
这是由于useEffect
导致的:如果您不提供第二个参数,则此挂钩将在每次重新渲染组件时运行。
所以在您的代码中发生的情况如下:
如果您希望它仅在安装组件时运行,请提供一个空数组作为第二个参数:
useEffect(() => {
generateRandomPotentialPartner();
console.log(state.potentialParnter)
}, []);
答案 2 :(得分:1)
您应该添加an empty dependency array to the useEffect
以防止其循环:
useEffect(() => {
generateRandomPotentialPartner();
}, []);
如果要记录useEffect
更改后的结果,则可能需要另一个state
:
useEffect(() => {
console.log(state.potentialParnter);
}, [state]);
答案 3 :(得分:1)
更改此
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)
}
我希望这对您有用。我的答案在解释其他答案时基于相同的原理,因此无需重复说明。