如何从Redux导出全局可用的desktop状态值?
这问题我之前也碰到过,复用Redux里的desktop状态确实能减少重复的mapStateToProps代码,给你几个实用的方案,看你用的是函数组件还是类组件:
方案1:用Reselect创建可复用选择器(推荐)
Reselect是Redux官方推荐的选择器库,自带缓存机制,能避免不必要的状态计算,非常适合复用这类重复的状态提取逻辑。
步骤如下:
- 新建一个专门存放选择器的文件,比如
src/selectors/responsive.js - 在文件中编写选择器:
import { createSelector } from 'reselect'; // 先获取redux-responsive在store中的根状态(默认key是`browser`,如果你自定义了key,替换成你的自定义key) const selectBrowserState = state => state.browser; // 创建可复用的选择器,提取desktop值 export const selectIsDesktop = createSelector( [selectBrowserState], browserState => browserState.desktop );
之后在任意组件里直接导入使用:
import { useSelector } from 'react-redux'; import { selectIsDesktop } from '../selectors/responsive'; function MyComponent() { const isDesktop = useSelector(selectIsDesktop); return <div>{isDesktop ? '当前是桌面端视图' : '当前是移动端视图'}</div>; }
方案2:自定义Hook(函数组件首选)
如果你的项目全是函数组件,写个自定义Hook会更简洁,直接封装useSelector和选择器的逻辑:
- 新建
src/hooks/useIsDesktop.js:
import { useSelector } from 'react-redux'; import { selectIsDesktop } from '../selectors/responsive'; export const useIsDesktop = () => { // 直接返回处理后的desktop状态 return useSelector(selectIsDesktop); };
组件里使用时更清爽:
import { useIsDesktop } from '../hooks/useIsDesktop'; function Header() { const isDesktop = useIsDesktop(); return isDesktop ? <DesktopHeader /> : <MobileHeader />; }
方案3:高阶组件(适配类组件)
如果项目里还有类组件,高阶组件(HOC)是个不错的选择,能把desktop状态作为props注入组件:
- 新建
src/hocs/withDesktop.js:
import { connect } from 'react-redux'; import { selectIsDesktop } from '../selectors/responsive'; // 创建HOC,自动注入isDesktop属性 export const withDesktop = connect(state => ({ isDesktop: selectIsDesktop(state) }));
类组件里使用:
import React from 'react'; import { withDesktop } from '../hocs/withDesktop'; class Sidebar extends React.Component { render() { return this.props.isDesktop ? ( <FullSidebar /> ) : ( <CollapsedSidebar /> ); } } // 用HOC包裹组件,注入isDesktop export default withDesktop(Sidebar);
注意点:
- 确认redux-responsive在store中的key:如果当初创建reducer时用了自定义key(比如
createResponsiveStateReducer({ key: 'viewport' })),记得把选择器里的state.browser改成state.viewport。 - Reselect的缓存:只有当
browser状态变化时,selectIsDesktop才会重新计算,能提升组件性能,比直接写state => state.browser.desktop更高效。
内容的提问来源于stack exchange,提问作者Fellow Stranger
相关产品推荐
相关产品推荐

