module-react-redux

Standalone Redux store creator for React components


Keywords
react, redux, module, react-redux, standalone
License
MIT
Install
npm install module-react-redux@1.0.0

Documentation

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

License

MIT