Che*_*iex 27 reactjs react-redux react-hooks
最近我正在阅读 react-redux 文档https://react-redux.js.org/next/api/hooks 并且有一个与平等比较和更新相关的部分,它说:
多次调用 useSelector(),每次调用返回一个字段值。
第一种方法:
const { open, importId, importProgress } = useSelector((importApp) => importApp.productsImport);
Run Code Online (Sandbox Code Playgroud)
第二种方法:
const open = useSelector((importApp) => importApp.productsImport.open);
const importId = useSelector((importApp) => importApp.productsImport.importId );
const importProgress = useSelector((importApp) => importApp.productsImport.importProgress);
Run Code Online (Sandbox Code Playgroud)
那么有什么真正的区别吗?或者由于破坏 useSelector 钩子会在检查引用时遇到麻烦?
小智 26
只是为了奠定基础:当一个动作被分派时,你传递给的选择器useSelector()将被调用。如果它返回的值与上次调度 action 时返回的值不同,则组件将重新渲染。
破坏确实是错误的方法,但这里的最佳答案完全无关紧要。文档指的是选择器每次都创建一个新对象的场景,就像您在mapStateToProps()函数中所做的那样。这将导致组件在每次分派动作时重新渲染,无论该动作做什么,因为即使实际数据没有更改,选择器返回的值在技术上也是内存中的不同对象。在这种情况下,您需要担心严格相等和浅相等比较。但是,您的选择器并不是每次都创建一个新对象。如果分派的操作没有修改importApp.productsImport,它将是内存中与以前完全相同的对象,从而呈现所有这些没有实际意义的内容。
相反,这里的问题是您正在选择整个状态切片,而您实际上只关心该切片的一些特定属性。考虑到importApp.productsImport可能有其它特性除了刚刚open,importId和importProgress。如果这些其他属性发生变化,那么您的组件将不必要地重新渲染,即使它没有引用它们。原因很简单:选择器返回importApp.productsImport,并且那个对象改变了。终极版无法知道的方式open,importId和importProgress是你真正关心,因为唯一的属性,你没有选择那些性能; 您选择了整个对象。
因此,要选择多个属性而不进行不必要的重新渲染,您有两个选择:
useSelector()挂钩,每个挂钩选择您商店中的一个属性。useSelector()钩子和一个选择器,将商店中的多个属性组合成一个对象。你可以这样做:
state并返回它。如果你这样做,你会再有大约严格的平等和浅相等比较担心。为此,我觉得多个useSelector()钩子实际上是要走的路。文档特别提到
每次调用 useSelector() 都会创建一个对 Redux 存储的单独订阅。
但是,纯粹出于这个原因,与单个调用相比,多个调用是否真的会导致真正的性能损失,我认为还有待观察,在我看来,担心这可能是过度优化,除非你有一个巨大的应用程序数百或数千个订阅。如果您使用单个useSelector()钩子,那么此时您基本上只是在编写一个mapStateToProps函数,我觉得这会挫败一开始使用钩子的很多吸引力,尤其是在您编写 TypeScript 时。如果您随后想要对结果进行解构,那会使它变得更加麻烦。我也认为使用多个钩子绝对更符合钩子 API 的一般精神。
Shr*_*a S 13
当一个动作被分派到 Redux 存储时,useSelector() 只做一个严格的“===”引用比较。这不会进行浅层检查。
因此,如果您想从存储中检索多个值,则必须多次调用 useSelector(),每次调用都会从 state 中返回一个字段值。或者使用shallowEqual在react-redux:
import { shallowEqual, useSelector } from 'react-redux'
const data = useSelector(state => state.something, shallowEqual)
Run Code Online (Sandbox Code Playgroud)
详细解释请参考https://react-redux.js.org/next/api/hooks#equality-comparisons-and-updates。
如何选择多个状态::
const [village, timeZone, date] = useSelector((state) => [
state.active_village,
state.time_zone,
state.date,
], shallowEqual);
Run Code Online (Sandbox Code Playgroud)
这个答案没有太多技术细节。请查看其他答案以获得更好的理解。在这里,我仅提及用例场景。希望您会发现它有帮助:
假设:productsImport仅包含您提到的字段(open、importId、importProgress)
1.假设您要使用 useSelector 获取单个组件中的所有字段,那么我会说您应该使用第一种方法。因为使用第二种方法将添加几行额外的代码,但没有其他好处。无论如何,每当任何字段的值更新时,您的组件都会重新渲染。
2.现在,假设您正在一个组件(Component1)中使用和更新importId,并在另一个组件(Component2)中使用和更新其余字段。而且,这些组件也应该呈现在同一窗口/屏幕上。那么你应该使用第二种方法。
Component1:
const importId = useSelector((importApp) => importApp.productsImport.importId );
Component2:
const open = useSelector((importApp) => importApp.productsImport.open);
const importProgress = useSelector((importApp) => importApp.productsImport.importProgress);
if you want to use only one selector:
const [open, importProgress] = useSelector((importApp) =>[importApp.productsImport.open, importApp.productsImport.importProgress],
shallowEqual);
'Note: Here do not forget to use shallowEqual. Otherwise, your component will rerender on every useSelector() call.'
Run Code Online (Sandbox Code Playgroud)
如果您将在此处使用第一种方法,那么每次更新任何字段时,您的两个组件都会重新渲染。
| 归档时间: |
|
| 查看次数: |
8502 次 |
| 最近记录: |