假设我们正在使用商店中一个名为CustomerProfile
的对象来处理客户配置文件页面。
export interface ICustomerProfileState {
status: string,
customerId: number,
contactInfo: IContactInfo,
financialInfo: IFinancialInfo
};
正如我们所看到的,这个对象由一些简单的属性和更复杂的属性组成。在CustomerProfile.tsx
页面上,让我们比较两种跟踪和更新相关属性状态的方法。第一种方法是对要跟踪的单个状态属性useSelector
:
const status = useSelector((state) => state.customerProfile.status)
const preferredName = useSelector((state) => state.customerProfile.contactInfo.preferredName)
const altName1 = useSelector((state) => state.customerProfile.contactInfo.alternateName1);
const altName2 = useSelector((state) => state.customerProfile.contactInfo.alternateName2);
const preferredPayment = useSelector((state) => state.customerProfile.paymentInfo.preferredPaymentMethod;
让我们将其与第二种方法进行比较——简单地跟踪对象本身:
const customerProfile = useSelector((state) => state.customerProfile);
在关于钩子的Redux文档中,特别是useSelector,它说:
调度操作时,useSelector((将对上一个选择器结果值和当前结果值进行引用比较。如果它们不同,组件将被迫重新渲染。如果它们相同,则组件将不会重新渲染。
这让我相信,上面的比较可能是相同的,因为无论是一个属性更改还是整个对象,整个组件都将重新渲染。但在我们的第二种方法中,即useSelector(...state.customerProfile)
,我假设,如果与customerProfile
的组件属性无关,我们可能会不必要地重新渲染组件。
但是,也许useSelector
在幕后会发生更多的事情,以至于跟踪对象上的单个属性与跟踪整个对象本身之间存在性能差异?
这里不关心性能。任何一种都可以在任何React应用程序中执行良好。性能应该在你有了一个可以工作的应用程序并可以进行分析后考虑。通过分析确定实际的瓶颈。
至于使用哪种风格,请使用最容易阅读、维护最清晰的风格。IMO一个带破坏功能的选择器会更好。如果评测显示这会导致不必要的重新渲染,那么为每个状态组件创建单独的选择器,然后创建一个选择器,使用这些选择器将其放回一个对象中,这样组件中仍然只有一个useSelector
调用。
重新使用选择器并将其分层通常是最佳实践。