React - re-render 只有一个 child 组件的优雅方式?
React - elegant way to re-render just one child component?
我正在开发 table 组件。当我在 <tbody />
上左右滚动时,我希望它只更新 <theader />
的 xOffset,它位于一个单独的组件中,我将调用 <Header Component />
。结构如下:
<Parent Component >
<Header Component />
<Very Expensive Body divs/>
<Very Expensive Body divs/>
<Very Expensive Body divs/>
</Parent Component >
滚动侦听器在 parent 组件上,xOffset 是 Parent 组件状态的一部分。当我左右滚动时,它也 re-renders re-render body 非常昂贵的组件。
对于 re-render 的 Header 组件,我有哪些选择?
1) 使用 Redux 和选择器。 Parent 组件将 xOffset 分派到应用程序状态,而 <Header Component />
仅在选择器上侦听它。好像矫枉过正了...
2) 我将所有 <Very Expensive Body Comp divs >
分解成它们自己的组件,并使用 ShouldComponentUpdate,这样它就不会 re-render 如果除 xOffset 之外的一切都保持不变。这看起来并不过分,但我觉得我将要处理同样的问题,因为我必须将滚动侦听器放在这个新组件上......然后使用 parent 组件作为中介..oof。
还有第三种更优雅的方案吗?
我希望有一种方法可以将函数传递给 <Header Component />
,这样当 parent 组件左右滚动时,它会使用该函数来更新 <Header Component />
这将导致它变为 re-render。
如果我理解正确,一种选择是执行以下操作:
<Parent Component >
<Header Component />
{ this.getVeryExpensiveBodyDivs() }
</Parent Component >
并让 getVeryExpensiveBodyDivs
第一次生成并缓存 div,然后如果它们在缓存中,则仅从缓存中访问它们。缓存只是一个实例变量 (this.cachedVeryExpensiveBodyDivs
).
然后,在您的 table 组件的 componentWillReceiveProps
中,您可以检查是否有任何应该影响非常昂贵的主体 div 的道具发生变化。如果道具更改会影响非常昂贵的主体 div,请清除缓存。下次调用 getVeryExpensiveBodyDivs
时,它将重新生成并重新缓存 div。
选项2!将非常昂贵的 div 标签分解成它们自己的组件并使用 shouldComponentUpdate
。将所有元素保留在一个 render()
函数中并不能像您开始看到的那样很好地扩展。使用 React 的全部好处是您可以创建简单、可重用的组件并使用这些组件构建更复杂的 UI。您似乎打算将所有内容都保留在一个组件中,但这实际上是 React 中的 anti-pattern。
但是,不要向每个组件添加新的滚动侦听器。相反,只需像您正在做的那样将它保留在 parent 组件上,并将滚动值作为道具传递给所有新组件。如果它们只需要在滚动一定数量的屏幕后更改,您可以在每个 child 的 shouldComponentUpdate
函数中更新它。
我正在开发 table 组件。当我在 <tbody />
上左右滚动时,我希望它只更新 <theader />
的 xOffset,它位于一个单独的组件中,我将调用 <Header Component />
。结构如下:
<Parent Component >
<Header Component />
<Very Expensive Body divs/>
<Very Expensive Body divs/>
<Very Expensive Body divs/>
</Parent Component >
滚动侦听器在 parent 组件上,xOffset 是 Parent 组件状态的一部分。当我左右滚动时,它也 re-renders re-render body 非常昂贵的组件。
对于 re-render 的 Header 组件,我有哪些选择?
1) 使用 Redux 和选择器。 Parent 组件将 xOffset 分派到应用程序状态,而 <Header Component />
仅在选择器上侦听它。好像矫枉过正了...
2) 我将所有 <Very Expensive Body Comp divs >
分解成它们自己的组件,并使用 ShouldComponentUpdate,这样它就不会 re-render 如果除 xOffset 之外的一切都保持不变。这看起来并不过分,但我觉得我将要处理同样的问题,因为我必须将滚动侦听器放在这个新组件上......然后使用 parent 组件作为中介..oof。
还有第三种更优雅的方案吗?
我希望有一种方法可以将函数传递给 <Header Component />
,这样当 parent 组件左右滚动时,它会使用该函数来更新 <Header Component />
这将导致它变为 re-render。
如果我理解正确,一种选择是执行以下操作:
<Parent Component >
<Header Component />
{ this.getVeryExpensiveBodyDivs() }
</Parent Component >
并让 getVeryExpensiveBodyDivs
第一次生成并缓存 div,然后如果它们在缓存中,则仅从缓存中访问它们。缓存只是一个实例变量 (this.cachedVeryExpensiveBodyDivs
).
然后,在您的 table 组件的 componentWillReceiveProps
中,您可以检查是否有任何应该影响非常昂贵的主体 div 的道具发生变化。如果道具更改会影响非常昂贵的主体 div,请清除缓存。下次调用 getVeryExpensiveBodyDivs
时,它将重新生成并重新缓存 div。
选项2!将非常昂贵的 div 标签分解成它们自己的组件并使用 shouldComponentUpdate
。将所有元素保留在一个 render()
函数中并不能像您开始看到的那样很好地扩展。使用 React 的全部好处是您可以创建简单、可重用的组件并使用这些组件构建更复杂的 UI。您似乎打算将所有内容都保留在一个组件中,但这实际上是 React 中的 anti-pattern。
但是,不要向每个组件添加新的滚动侦听器。相反,只需像您正在做的那样将它保留在 parent 组件上,并将滚动值作为道具传递给所有新组件。如果它们只需要在滚动一定数量的屏幕后更改,您可以在每个 child 的 shouldComponentUpdate
函数中更新它。