如果在子表单中键入太快,则使用 Effect 对导致无限循环

useEffect pair causing infinite loop if typing too fast in sub-form

提问人:Horkos 提问时间:10/18/2023 最后编辑:skyboyerHorkos 更新时间:11/20/2023 访问量:37

问:

我有一个独立更新状态数组元素的表单,但是当在表单中“键入太快”时,它的制作方式会导致无限循环。

状态应是项目的副本。每个部分都可以有多个部分,我们可以修改表单中的每个数据。sectiondata.sectionsprofilesprofile

配置文件窗体中键入速度过快会导致 useEffect 部分无限循环。

这是通过前两个 useEffect 钩子中的 console.logs 记录的 - 组件中没有抛出过多的日志,因此必须将其绑定到组件ProfileFormsection

组件: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} />
   )

reactjs 数组 react-hooks 无限循环

评论


答:

0赞 SS87 11/20/2023 #1

我可以看到一连串的事件,由于你构建 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,然后就是循环。