我想创建一个组件Person,该组件完全受其状态控制。它还应该能够将从其父组件传递的道具更改(firstName,lastName)同步到状态。我有以下代码。它完成了我想要的同步道具到状态并在状态更改后重新渲染的工作。
但是我注意到的一个问题是,在父项更改触发DOM更新后,将调用useEffect。因此,最初的重新渲染是浪费的,因为我只希望在调用useEffect并更改状态后重新渲染。
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 <div>render {name}</div>;
}
export default Person;
我在https://codesandbox.io/s/sparkling-feather-t8n7m处创建了一个简单的演示。如果单击重新渲染按钮,则在控制台中,您将看到以下输出。第一个re-render!
是由我想避免的道具变更触发的。任何想法如何实现这一目标?我知道还有其他解决方案,例如使其完全不受控制,但我想知道此解决方案是否有任何解决方法
re-render!
state changed!
re-render!
答案 0 :(得分:1)
您将需要在useEffect中添加一个条件。像:
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)不会更新。
答案 1 :(得分:0)
根据doc
,这基本上是React的核心行为传递给useEffect的函数将在将渲染提交到屏幕后运行。
为了避免由副作用引起的错误。
我想您稍微简化了示例,但是您应该知道复制道具无条件声明是反模式 https://en.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti-pattern-unconditionally-copying-props-to-state
相反,您应该直接使用道具:
const Person = ({firstName, lastName}) => (
<div>render {firstName + lastName}</div>;
);