以属性作为依赖来反应useEffect进行无限循环

时间:2020-01-07 21:07:16

标签: reactjs typescript

我有一个组件:

const MyComp : React.FC<{ editing?: Data }> = ({editing = { title = '', description = '', date: new Date() } }) => {
    const [data, setData] = useState<Data>({...editing})
    useEffect(() => setData({...editing}), [editing])
    return (/* use data inside here to render component */)
}

问题在于useEffect正在循环播放,因此React检测到每个编辑道具都在变化,问题是我使用MyComp而没有任何这样的道具:

<MyComp></MyComp>

这真的让我感到困惑,我现在对React的工作方式有点迷茫,为什么会这样呢?

2 个答案:

答案 0 :(得分:7)

因为editing是一个对象。通过引用比较对象。如果不将prop editing传递给组件,则在每个渲染中,editing将在内存中收到一个新链接,因为您将默认值传递给了它。因此,useEffect将假定依赖关系已更改。

您可以将基本类型设置为依赖项。

const MyComp : React.FC<{ editing?: Data }> = ({editing = { title = '', description = '', date: new Date() } }) => {
    const [data, setData] = useState<Data>({...editing})
    useEffect(() => setData({...editing}), [editing.title, editing.description, editing.date.getTime()])
    return (/* use data inside here to render component */)
}

答案 1 :(得分:3)

发生这种情况是因为useEffect使用浅表比较。 您可以破坏对象

const {param1, param2} = editing;
useEffect(() => {
//logic goes here
}, [param1, param2]);

或者编写一个使用Lodash isEqual的自定义钩子