Experimental I didn't realise publishing this package to NPM would cause so many downloads. This package is still experimental so I would not currently recommend it for production use yet though I intend for it to production ready in the coming days.
Some middleware may not work with this library as all actions are pushed through each middleware in each module, so some middleware may not handle this scenario gracefully, though thunks and redux-observable have been tested.
Having to compile a list of possible reducers, state and/or middleware ahead-of-time is error prone (you forget to add a reducer/middleware) and time consuming (hunting down which reducers and middleware you need).
This has been resolved by using the redux-modules-enhancer that adds support for adding/removing modules after the store has been created.
In order to avoid polluting JSX code with boilerplate code for adding modules such as,
class MyComponent extends Component {
constructor(props, context) {
super(props, context);
this.context.store.add(myModule);
}
...
}
MyClass.contextTypes {
[store]: storeShape.required
}
this module provides a ReduxModule component that lets you add a module as part of the render step, for example,
import { connect } from "react-redux";
import { connectModules } from "react-redux-module";
import { createMyModule } from "./my-redux-module.js";
class MyComponent extends Component {
render() {
return
<div>
...
</div>
}
}
... mapStateToProps & mapDispatchToProps ...
export default connect(mapStateToProps, mapDispatchToProps, connectModules(createMyModule, MyComponent));
The only 2 dependencies required for use are,
- redux-modules-enhancer - use the modulesEnhancer from redux-modules-enhancer when creating your store to add support for adding/removing modules.
- react-redux - use the Provider component to ensure the store is part of the context.
import React from "react";
import { render } from "react-dom";
import { createStore } from "redux";
import modulesEnhancer from "redux-modules-enhancer";
const store = Redux.createStore(myreducer, myinitialState, modulesEnhancer());
render(
<Provider store={store}>
<MyApp />
</Provider>,
document.getElementById('root')
)
or, if you want to use other enhancers as well,
import { createStore, combine, applyMiddleware } from "redux";
const store = Redux.createStore(myreducer, myinitialState, combine(modulesEnhancer(), applyMiddleware(...)));
After that, you just wrap your component using connectModule and a factory method for creating your module,
import { ReduxModule } from "react-redux-module";
import { connectModules } from "react-redux-module";
import getModuleDefintion as getMyModuleDefintion from "./MyModule.js";
class MyComponent extends Component {
render() {
return
<div>
...
</div>
}
}
/* ... mapStateToProps & mapDispatchToProps ... */
export default connect(mapStateToProps, mapDispatchToProps, connectModules(getMyModuleDefintion())(MyComponent));
createMyModule(moduleId, options) => {
const moduleId = moduleId;
const initialState = { /* ... initial state ... */ }
const reducer = (state, action) => {
// .. reducer logic ..
}
const middleware = [ /* ... any middleware required for this module ... */ ];
const onload = dispatch => {
/* Any behaviour to take when the module is first loaded. */
}
const onunload = dispatch => {
/* Any behaviour to take when the module is removed from the store. */
}
return {
moduleId,
initialState,
reducer,
middleware,
onload,
onunload,
}
}
export const getModuleDefinition = (moduleId, options) => ({
moduleId: moduleId || `defaultModuleId`,
options: { defaultValue: 1, ...options }
});
export default getModuleDefinition;
connectModules(modulesDefinitions)(component);
- moduleDefinitons is an array of objects or an object containing
- moduleId The unique identifier for the module instance.
- options The options (if any) to be passed to the factory.
- factory A factory method for creating a new module instance with the signature (moduleId, options) => ReduxModuleObject;
- component is the component to be wrapped that relies on the given modules being loaded.
The method returns a Component that wraps the given component and will load the given modules when the component is constructed.