在回调函数中使用 setState 钩子时反应 太多的重新渲染



当我在用作组件回调的函数中使用 setState 钩子时,我从 React 收到太多重新渲染错误。

下面是一个无用的例子来演示我正在尝试做什么。

我有一个 Person 对象数组和一个宠物数组。每只宠物都有一个主人(=人(。 我想显示这个人和他拥有的宠物的名字。

我遍历 Person 数组,每个人都应该有一个 TestComponent。 TestComponent 需要一个人的名字和一个宠物的名字。

宠物名称在回调函数中计算,getPetByOwnerName该函数将遍历所有宠物,如果给定的人名与宠物的主人姓名匹配,它将返回该宠物名称。

如果一个人没有宠物,它应该使用setPets()将一个空的宠物对象添加到宠物列表中。

getPetByOwnerName函数内部setPets()导致Too many re-renders错误。

在这个例子中,这样做可能没有任何意义,但它是为了在一个更大的项目中重新创建一个我遇到的问题。

import React, { useState } from 'react'
import TestComponent from './TestComponent'
const TestPage = () => {
const [persons, setPersons] = useState([{name: 'Tom', age: 35}, {name: 'Fred', age: 50 }])
const [pets, setPets] = useState([{owner: 'Tom',name: 'Doggo'}])

const getPetByOwnerName = (name) => {
let petName = null
pets.map((pet, index) => {
if (pet.owner === name) {
petName = pet.name
}
return pet
})
if (!petName) {
const pet = {
owner: name,
name: ''
}
const updatedPets = pets
pets.push(pet)
setPets(updatedPets)
}
return petName
}
return (
<React.Fragment>
{
persons.map((person, index) => (
<TestComponent key={index} personName={person.name} petName={getPetByOwnerName(person.name)}></TestComponent>
))
}
</React.Fragment>
)
}
export default TestPage

测试组件:

import React from 'react'
const TestComponent = ({ personName, petName }) => {
return (
<React.Fragment>
<p>{personName} owns pet: {petName}</p>
</React.Fragment>
)
}
export default TestComponent

在使用效果中处理这种功能可能更好。您可以观察人的变化,然后相应地更新宠物。如下所示。

但是您的实际问题就在这一行if (!petName).当 petName 是一个空字符串时,它会进入这里并永久设置状态。您需要像if(!petName && petName !== '')这样的支票

useEffect(() => {
persons.map(person => {
const petIndex = pets.findIndex(p => p.owner === person.name);
if (petIndex === -1) {
const pet = {
owner: person.name,
name: ''
}
setPets(prevPets => ([...prevPets, pet]))
}
})
}, [persons]);

另外,作为旁注,当使用以前的状态来更新状态时,最好使用回调版本(请参阅上面示例中更新的 set pets(

由于这只是您实际问题的一个例子,因此最好在设置状态之前放置一个debugger;,看看为什么您如此频繁地设置它。

最新更新