React拆分库模块后如何在库中访问Redux Store?
我们有一个使用Redux维护全局状态的大型React项目,随着功能迭代,将各功能拆分为独立库模块引入根项目后,库模块无法访问Redux Store,报错信息如下:
Could not find "store" in either the context or props of "Connect(i)". Either wrap the root component in a
, or explicitly pass "store" as a prop to "Connect(i)".
场景复现:将依赖Redux状态的FilterLink组件移入独立的component-library模块并发布,在根项目的Footer组件中使用该组件时触发上述错误。
以下是几种可行的解决方案:
方法1:通过Props传递Redux相关状态与方法
让库组件完全解耦于Redux,不直接使用Redux的连接方法或hooks,改为接收根项目传递的状态数据和操作方法。
示例:
库模块中的FilterLink组件:
// component-library/src/FilterLink.js export default function FilterLink({ filter, currentFilter, onClick }) { return ( <button onClick={() => onClick(filter)} disabled={filter === currentFilter} style={{ marginLeft: '4px' }} > {filter} </button> ); }
根项目中使用时,从Redux获取状态和dispatch方法后传递给库组件:
// 根项目Footer组件 import { useSelector, useDispatch } from 'react-redux'; import FilterLink from 'component-library/FilterLink'; import { setVisibilityFilter } from '../actions'; function Footer() { const currentFilter = useSelector(state => state.visibilityFilter); const dispatch = useDispatch(); return ( <div> <span>Show: </span> <FilterLink filter="ALL" currentFilter={currentFilter} onClick={(filter) => dispatch(setVisibilityFilter(filter))} /> <FilterLink filter="ACTIVE" currentFilter={currentFilter} onClick={(filter) => dispatch(setVisibilityFilter(filter))} /> <FilterLink filter="COMPLETED" currentFilter={currentFilter} onClick={(filter) => dispatch(setVisibilityFilter(filter))} /> </div> ); }
这种方式通用性强,库组件无需依赖根项目的Redux配置。
方法2:共享Redux上下文
若需在库组件中直接使用Redux hooks(如useSelector、useDispatch),需满足两个核心条件:
- 库与根项目使用同一版本的React、react-redux和redux
- 根项目的
<Provider>已包裹整个应用(包含库组件)
关键配置:
在库的package.json中将react、react-redux、redux标记为peerDependencies,避免打包时重复引入这些依赖,导致上下文实例不一致:
// component-library/package.json { "peerDependencies": { "react": "^18.0.0", "react-redux": "^8.0.0", "redux": "^4.0.0" } }
之后即可在库组件中直接使用Redux hooks:
// component-library/src/FilterLink.js import { useSelector, useDispatch } from 'react-redux'; import { setVisibilityFilter } from './actions'; // 需保证action与根项目的Redux结构匹配 export default function FilterLink({ filter }) { const currentFilter = useSelector(state => state.visibilityFilter); const dispatch = useDispatch(); return ( <button onClick={() => dispatch(setVisibilityFilter(filter))} disabled={filter === currentFilter} style={{ marginLeft: '4px' }} > {filter} </button> ); }
注意:此方法要求库与根项目的Redux状态结构、action类型完全一致,否则会出现状态获取错误。
方法3:显式传递Store(不推荐)
若上述方法不适用,可在根项目中将Store通过props或自定义上下文传递给库组件。
示例:
库组件导出接收Store的高阶组件:
// component-library/src/FilterLink.js import { connect } from 'react-redux'; import { setVisibilityFilter } from './actions'; const FilterLink = ({ filter, currentFilter, onClick }) => ( <button onClick={onClick} disabled={filter === currentFilter} style={{ marginLeft: '4px' }} > {filter} </button> ); const mapStateToProps = (state, ownProps) => ({ currentFilter: state.visibilityFilter }); const mapDispatchToProps = (dispatch, ownProps) => ({ onClick: () => dispatch(setVisibilityFilter(ownProps.filter)) }); export default (store) => connect(mapStateToProps, mapDispatchToProps)(FilterLink);
根项目中传入Store并使用:
// 根项目Footer组件 import { store } from '../store'; import FilterLink from 'component-library/FilterLink'; const ConnectedFilterLink = FilterLink(store); function Footer() { return ( <div> <span>Show: </span> <ConnectedFilterLink filter="ALL" /> <ConnectedFilterLink filter="ACTIVE" /> <ConnectedFilterLink filter="COMPLETED" /> </div> ); }
此方式操作繁琐,会增加库与根项目的耦合度,仅适合特殊场景。
内容的提问来源于stack exchange,提问作者sai sandeep kothuri

