React props state syncing causes unnecessary first re-render
我想创建一个组件Person,该组件的状态完全受其控制。它还应该能够将从其父组件传递的道具更改(名字,姓氏)同步到状态。我有以下代码。它完成了我想要的工作,即在状态更改后将道具同步到状态并重新渲染。
但是我注意到的一个问题是,在父项更改触发DOM更新后,将调用useEffect。所以最初的重新渲染是浪费的,因为我只希望在useEffect被调用并且状态改变后重新渲染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import React,{useState, useEffect} from 'react'; const Person = ({firstName, lastName}) => { const [name, setName] = useState(firstName + lastName) useEffect(() => { setName(firstName + lastName); console.log("state changed!"); }, [firstName, lastName]) console.log("re-render!"); return render {name}; } export default Person; |
我在这里https://codesandbox.io/s/sparkling-feather-t8n7m创建了一个简单的演示。如果单击重新渲染按钮,则在控制台中,您将看到以下输出。我想避免的第一个
1 2 3 | re-render! state changed! re-render! |
您将需要在useEffect中添加一个条件。像:
1 2 3 4 5 6 7 8 9 10 | const [didUpdate, setDidUpdate] = useState(false); useEffect(() => { if(didUpdate){ setName(firstName + lastName); console.log('state changed!'); } else { setDidUpdate(true); } }, [firstName, lastName]); |
此处重现componentDidUpdate()行为。
在第一个渲染中,安装了组件,didUpdate初始化为false,因此该效果将仅在下一次更新时将其设置为true。
请注意,当prop更改时,使用prop初始化的状态(useState)不会更新。
根据doc
,这基本上是React的核心行为
The function passed to useEffect will run after the render is committed to the screen.
以避免副作用引起的错误。
我想您稍微简化了您的示例,但是您应该知道复制道具以无条件声明是一种反模式https://en.reactjs.org/blog/2018/06/07/you-probably-dont -need-derived-state.html#anti-pattern-unconditionally-copys-props-to-state
相反,您应该直接使用props:
1 2 3 | const Person = ({firstName, lastName}) => ( render {firstName + lastName}; ); |