Create Module Redux
Standalone Redux store creator for React components. Requires a working knowledge of React, Redux, and React-Redux.
Overview
module-react-redux
makes it easy to create and connect to a new Redux store. Please note that it is not intended to be used to create the main app store. Rather, it is meant for creating a standalone, component-level store, for the times you require one.
Redux is intended to have only a single store. However, there are valid reasons for multiple stores as noted in their docs. We created module-react-redux
with these cases in mind. Hence, the most prevalent use case will be for storing noisy or peripheral states that don't necessarily need to be part of the main store. Moreover, this library will be most useful for React applications adhering the to the Component/Container pattern with a strong emphasis on functional components.
Installation
module-react-redux
can be installed directly through npm:
# with NPM
$ npm install --save module-react-redux
# with yarn
$ yarn add module-react-redux
createModuleReactRedux
const { Context, Provider, connect } = createModuleReactRedux({
context,
defaultState,
reducer,
middleware,
})
Props Object
Name | Type | Description |
---|---|---|
context | Object |
The context of the store. If not provided, createModuleReactRedux will create its own context. |
defaultState | Object |
The initial state of the store. Must be provided. |
reducer | Function |
The reducer for the store. Must be provided. |
middleware | Array |
Custom middlewares. |
Return Object
Name | Description |
---|---|
Context | The instantiated context of the store. |
Provider | Makes the new store available to any nested components that have been wrapped in connect() function. |
connect |
react-redux connect function that connects to our new store. |
Usage
Here is a basic example with the following Component/Container structure.
App/
appStates.js
appReducers.js
appActions.js
appSelectors.js
components/
SomeComponent/
SomeComponentModule.jsx
SomeComponent.jsx
SomeComponentContainer.jsx
module/
states.js
reducers.js
actions.js
selectors.js
index.js
Creating and connecting to a new store
We have a basic component, SomeComponent
.
// components/SomeComponent/SomeComponent.jsx
import React from 'react'
const SomeComponent = ({ something, doSomething }) => (
<div onClick={doSomething}>{something}</div>
)
export default SomeComponent
We instantiate a standalone store for SomeComponent in components/SomeComponent/module/index.js
. We supply the reducer and state specific to SomeComponent
. In return, createModuleReactRedux
generates a Provider
, Context
of the standalone store, and a connect
that will connect specifically to this store.
// components/SomeComponent/module/index.js
import { createModuleReactRedux } from 'module-react-redux'
const reducer from 'components/SomeComponent/module/reducers.js'
const defaultState from 'components/SomeComponent/module/states.js'
const { connect, Context, Provider } = createModuleReactRedux({ reducer, defaultState })
export {
connect,
Context,
Provider,
}
Now, we can utilize this new store we've created in SomeComponentContainer
.
// components/SomeComponent/SomeComponentContainer.jsx
import { connect } from 'components/SomeComponent/module'
import { doSomething } from 'components/SomeComponent/module/actions.js'
import { selectSomething } from 'components/SomeComponent/module/selectors.js'
import SomeComponent from './SomeComponent.jsx'
const mapStateToProps = (state) => ({
something: selectSomeState(state)
})
const mapDispatchToProps = (dispatch) => ({
doSomething: () => dispatch(doSomething()),
})
const SomeComponentContainer = connect(mapStateToProps, mapDispatchToProps)(SomeComponent)
export default SomeComponentContainer
Lastly, SomeComponenModule
will provide the correct context to our container.
// components/SomeComponent/SomeComponentModule.jsx
import React from 'react'
import { Provider as SomeComponentProvider } from 'components/SomeComponent/module'
import SomeComponentContainer from 'components/SomeComponent/SomeComponentContainer'
const SomeComponentModule = (props) => (
<SomeComponentProvider>
<SomeComponentContainer {...props} />
</SomeComponentProvider>
)
export default SomeComponentModule
Connecting to the standalone store and the main store
We can connect to both the standalone store and the main store by composing our component. We will be using compose from redux in this example.
// App/components/SomeComponent/SomeComponentContainer.jsx
import { connect } from 'react-redux'
import { compose } from 'redux'
import { doAppSomething } from 'appActions.js'
import { selectAppSomething } from 'appSelectors.js'
import { connect as connectSomeComponent } from './module'
import { doSomething } from 'components/SomeComponent/module/actions'
import { selectSomething } from 'components/SomeComponent/module/selectors'
import SomeComponent from './SomeComponent'
const mapSomeComponentStateToProps = (state) => ({
something: selectSomeState(state)
})
const mapSomeComponentDispatchToProps = (dispatch) => ({
doSomething: () => dispatch(doSomething()),
})
const mapStateToProps = (state) => ({
appSomething: selectAppSomething(state),
})
const mapDispatchToProps = (dispatch) => ({
doAppSomething: () => dispatch(doAppSomething()),
})
const SomeComponentContainer = compose(
connect(mapStateToProps, mapDispatchToProps),
connect(mapSomeComponentStateToProps, mapSomeComponentDispatchToProps)
)(SomeComponent)
export default SomeComponentContainer
Roadmap
- Add support for react-redux hooks api once custom context for hooks are supported.
License
MIT