【问题标题】:Avoid parent component re-rendering when Child component updates parent state,避免子组件更新父状态时父组件重新渲染,
【发布时间】:2022-06-29 21:49:51
【问题描述】:

在我们的反应应用程序中,我们有父子组件。子组件调用父方法更新父状态值。这是示例代码

//父组件

const parent = ({ items }) => {
    const [information, setInformation] = useState([]);
    const updateParentInformation = (childUpdate) => {
         setInformation(information + childUpdates)
    }
    return (
        <div>
            <div>{information}</div>
            ...
            {items.map((item) => {
                return (
                    <ChildComponent item={item} updateParentInformation={updateParentInformation} />
            )})}
        </div>
    )
}

//子组件

const ChildComponent = ({ item, updateParentInformation }) => {
    useEffect(() => {
        const cardInformation = calculateCardInformation(item)
        updateParentInformation(cardAmpScripts)
     }, [item])
    return (
        <div>
            .....
        </div>
    )
}

所以子组件调用父组件的updateParentInformation函数来更新父状态,从而重新渲染父组件。我这里有几个问题

  1. 在某些情况下,我们可能有 100-150 个子组件,在这种情况下我们的父母会重新渲染很多,如何避免这种情况。我们可以通过这段代码避免这种情况

    ....
     let recievedUpdates = 0
     const updateParentInformation = (childUpdate) => {
          recievedUpdates++
          if(recievedUpdates == items.length {
              setInformation(information + childUpdates)
          }
     }
    

如果这是一个可能的解决方案,那么我有问题 2

  1. 当子组件调用父组件的 updateParentInformation 时如何避免竞态条件。例如,孩子 1 被称为 updateParentInformation 函数,同时孩子 2 也被称为 updateParentInformation,在这种情况下,我们可能会丢失一个孩子的更新。

【问题讨论】:

标签: reactjs use-effect use-ref


【解决方案1】:

不能避免这种情况,因为如果组件的内部状态发生变化,它总是必须重新渲染。因此,您有两种可能的方法来解决这种情况下的性能问题:

  1. 将您的孩子包装在React.memo() 中,这样每次您的孩子更新父组件中的状态时,所有不关心并且没有收到更新状态作为道具的孩子都不会重新渲染。
  2. 使用全局状态管理器(建议)。如果您有数百个使用通用状态的组件,并且这些状态可能是通过 props 钻取的,从而导致大量不必要的重新渲染,那么您肯定会受益于 State Manager,例如 Redux ,这样只有使用特定状态切片的组件才会在该状态更改时重新渲染。

在任何情况下,如果在树顶部的组件(父母)中执行繁重的计算,请始终将它们包装在 useMemo() 钩子中,函数和 useCallback() 也是如此,这样您将能够解决您的大部分性能问题。

关于race-condition 的问题,react useState 可以与这样的回调一起使用,以确保它在执行时可以访问该状态的最新值:

const [state, setState] = useState(0)
setState(currentState => currentState + 1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 2020-05-04
    相关资源
    最近更新 更多