提问人:Horkos 提问时间:10/18/2023 最后编辑:skyboyerHorkos 更新时间:11/20/2023 访问量:37
如果在子表单中键入太快,则使用 Effect 对导致无限循环
useEffect pair causing infinite loop if typing too fast in sub-form
问:
我有一个独立更新状态数组元素的表单,但是当在表单中“键入太快”时,它的制作方式会导致无限循环。
状态应是项目的副本。每个部分都可以有多个部分,我们可以修改表单中的每个数据。section
data.sections
profiles
profile
在配置文件
窗体中键入速度过快会导致 useEffect 部分
无限循环。
这是通过前两个 useEffect 钩子中的 console.logs 记录的 - 组件中没有抛出过多的日志,因此必须将其绑定到组件ProfileForm
section
组件:sections
const {data, setData} = props
const [sections, setSections] = React.useState<any[]>(data.sections)
// how sections are made
// sections = [
// {
// name: "",
// profiles: [
// { name: "" }
// ]
// }
// ]
React.useEffect(() => {
if (sections && (sections !== data.sections)) {
setData({...data, sections: sections})
}
}, [sections])
React.useEffect(() => {
if (data.sections && (data.sections !== sections)) {
setSections(data.sections)
}
}, [props])
// ...
{
sections && sections.map((section: any, sectionIndex: number) => {
return (
<>
{section.name}
{
section.profiles && section.profiles.map((profile: any, profileIndex: number) => (
<ProfileForm
key={profileIndex}
{...{sections, setSections, sectionIndex, profileIndex, profile, t}}
/>
))
}
</>
)
})
}
组件:person
const {sectionIndex, profileIndex} = props
const [profile, setProfile] = React.useState(props.profile)
React.useEffect(() => {
if (profile && (profile !== props.profile)) {
handleProfileChange(sectionIndex, profileIndex)
}
}, [profile])
React.useEffect(() => {
if (props.profile && (props.profile !== profile)) {
setProfile(props.profile)
}
}, [props])
const handleProfileChange = (sectionIndex: number, profileIndex: number) => {
let _profiles= sections[sectionIndex].profiles
_profiles.splice(profileIndex, 1, profile)
let _sections = [...sections]
_sections.splice(si, 1, { name: _sections[sectionIndex].name, profiles: _profiles })
setSections([..._sections])
}
return (
<input onChange={(e: any) => setProfile({...profile, name: e.target.value})} value={profile.name} />
)
答:
我可以看到一连串的事件,由于你构建 React 逻辑的方式,这些事件将导致无限循环;
当它调用 setProfile() 的 Person 组件中的输入发生变化时,该组件将重新渲染,然后触发第一个 useEffect。这反过来又调用 handleProfileChange(),然后它本身在 Sections 组件(问题所在)中调用 setSections()。
然后 Sections 组件重新渲染并调用它的第一个 useEffect,因为 setSections() 是从 Person 组件调用的,并且“sections”已更改(它在第一个 useEffects 依赖项数组中)。然后,此 useEffect 调用 setData()。
现在这里是无限循环开始的地方,因为你通过 props 将 setData() 和数据从父组件传递到 Sections 组件中,这本身很好,但你有第二个 useEffect,它的依赖数组中有 'props'。第一个 useEffect 刚刚调用了 setData(),所以 'data' 刚刚更改,因此现在触发了第二个 useEffect。第二个 useEffect 然后调用 setSections(),它再次触发第一个调用 setData() 的 useEffect,然后就是循环。
评论