使用createSelector与自定义useAppSelector,哪种方案更优?
两种方案的适用场景与取舍建议
核心差异先搞清楚
createSelector是Redux Toolkit自带的记忆化选择器:只有当它依赖的状态片段真的变化时,才会重新计算返回值,能有效避免组件无意义重渲染。- 你写的自定义
useAppSelector如果只是简单封装useSelector(state => state.documentHub.xxx),本质就是直接读状态属性,没有记忆化能力——每次组件渲染都会跑一遍这个选择函数,要是父状态有更新但你要的那个属性没变,组件也可能跟着重渲染。
适合用自定义useAppSelector的场景
- 你要拿的是单一、顶层的状态字段,比如
state.documentHub.isLoading、state.documentHub.currentTab这种直接的属性,而且组件对重渲染不敏感(比如只是个按钮、文本展示组件)。 - 想减少重复代码,把常用的属性封装成独立小Hook,比如:
// 封装成专用Hook const useDocHubLoading = () => useAppSelector(state => state.documentHub.isLoading); const useDocHubCurrentTab = () => useAppSelector(state => state.documentHub.currentTab);
这样组件里直接调用const isLoading = useDocHubLoading()就行,不用每次写长串的state.documentHub.xxx。
必须保留createSelector的场景
- 当你需要计算派生状态的时候,比如从
state.documentHub.documents数组里过滤符合条件的文档,或者组合多个状态片段算新值,比如:
const selectFilteredDocs = createSelector( [state => state.documentHub.documents, state => state.documentHub.filterKeyword], (docs, keyword) => docs.filter(doc => doc.title.includes(keyword)) );
这时候createSelector的记忆化就很关键——它会缓存计算结果,只有documents或filterKeyword变了才会重新过滤,不会每次状态更新都白跑一遍过滤逻辑,性能提升明显。
- 多个组件都要用同一个派生状态时,
createSelector能让所有组件共享同一个计算结果,避免重复计算,省资源。
最优解:两者结合用
完全没必要二选一,应该根据需求混合使用:
- 读单一属性的场景,用自定义
useAppSelector封装成专用Hook,减少冗余。 - 处理派生状态时,保留
createSelector,还可以把它也封装到Hook里,比如:
const useFilteredDocs = () => { // 用useMemo缓存createSelector实例,避免每次渲染重新创建 const selectFiltered = useMemo(() => createSelector( [state => state.documentHub.documents, state => state.documentHub.filterKeyword], (docs, keyword) => docs.filter(doc => doc.title.includes(keyword)) ), []); return useAppSelector(selectFiltered); };
这样既享受到记忆化的性能优势,组件调用也简单,直接const filteredDocs = useFilteredDocs()就行。
总结一下:
- 别盲目替换
createSelector,它在复杂派生状态场景下的性能优势是没法替代的。 - 自定义
useAppSelector适合简化单一属性的读取,减少重复代码。 - 最好的方式是两者搭配,根据不同的状态需求选对应的实现。
内容的提问来源于stack exchange,提问作者Zabeeh Ullah
相关产品推荐
相关产品推荐

