关于reactjs:React props状态同步导致不必要的第一次重新渲染

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创建了一个简单的演示。如果单击重新渲染按钮,则在控制台中,您将看到以下输出。我想避免的第一个re-render!是由道具更改触发的。任何想法如何实现这一目标?我知道还有其他解决方案,例如使其完全不受控制,但我想知道此解决方案是否有任何解决方法

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};
);