基本问题
我有一个Redux商店,其中包含以下数据:
foo: {
currentId: 1,
things: [{id: 1}, {id: 2}),
}
我想在某处创建一个实用方法 (例如在Foo
单例对象上),这样我的代码中的任何模块都可以这样做:
import Foo from 'foo';
foo.getCurrentFoo(); // returns foo.thins[foo.currentId];
但是我无法弄清楚放在哪里。
尝试失败
我最初的尝试是创建一个Foo
组件单例:
// Foo.js
class FooBase extends React.Component {
getCurrentFoo() {
return this.state.foo.things[this.state.foo.currentId];
}
}
const Foor = connect((state) => state.foo)(FooBase);
export default new FooWrapper();
但这不起作用。 Redux抱怨财产store
不存在(当我new FooWrapper()
时)。这是有道理的,因为我的组件不在<Provider />
内。但是,我只想要一个独立的实用程序类/对象,而不是DOM中的实际内容,它排除了<Provider/>
。
如何制作一个类似上述方法的方法,实际上有效,不涉及<Provider />
......我在哪里放?
答案 0 :(得分:1)
react-redux
助手的好处在于,它们允许您使用connect()
和<Provider />
通过React的context自动将商店传递给子组件。但是,这并不一定意味着您 使用这些帮助程序,尤其是在不使用React的代码库区域。
所以问题在于:connect()
和<Provider />
通过让我们的React组件访问商店的单例实例来帮助我们,但我们如何在connect()
的某个地方访问此商店并且<Provider />
无法使用?
我认为这里最简单的解决方案是创建一个保留商店的单例类,因此任何非React模块仍然可以使用商店。
所以,假设您正在创建这样的商店:
<强> init.js 强>
import {createStore} from 'redux';
const initialState = {
currentId: 1,
things: ['foo', 'bar']
};
const reducer = (state = initialState, action) => {
if (action.type === 'SET_CURRENT_ID') {
return Object.assign({}, state, {
currentId: action.id
});
}
return state;
};
const store = createStore(reducer);
此商店采取类型为SET_CURRENT_ID
的操作,该操作只返回一个新状态,其中currentId
属性已更改为传递给它的任何内容。然后,您可以通过执行类似store.getState().things[store.getState().currentId]
的操作来获取当前的“事物”。因此,让我们创建一个Singleton类,它可以保留到商店并提供此功能的包装。
<强> store.js 强>
class Store {
constructor() {
this._store = undefined;
}
setStore(store) {
this._store = store;
}
getCurrentThing() {
if (this._store) {
const {things, currentId} = this._store.getState();
return things[currentId];
}
}
setCurrentThing(id) {
if (this._store) {
const action = {
type: 'SET_CURRENT_ID',
id
};
this._store.dispatch(action);
}
}
}
export let singletonStore = new Store();
此类在第一次使用时创建实例,并在以后的每个时间使用该实例。因此,当您最初创建商店时,只需导入此类并调用setStore()
。
<强> init.js 强>
import {singletonStore} from './store';
singletonStore.setStore(store);
然后,使用singletonStore
的每个后续文件将具有相同的状态。
<强> test.js 强>
import {singletonStore} from './store';
console.log(singletonStore.getCurrentThing()); // 'bar'
singletonStore.setCurrentThing(0);
console.log(singletonStore.getCurrentThing()); // 'foo'
这应该可以正常运行,因为您需要在模块中使用您的商店,这些模块无法通过connect()
和<Provider />
神奇地传递商店。