sub-redux
TypeScript icon, indicating that this package has built-in type declarations

1.0.0-alpha.1 • Public • Published

SubRedux

npm version npm

sub-redux is a library that allows you to dynamically create, use and destroy multiple isolated redux 'sub-apps'.

Getting started

Install

$ npm install --save sub-redux

or

$ yarn add sub-redux

Usage Example

Include the SubRedux reducer and middleware in your main store:

import { applyMiddleware, combineReducers, createStore } from 'redux';
import {
  middleware as subReduxMiddleware,
  reducer as subReduxReducer,
} from 'sub-redux';

const rootReducer = combineReducers({
  subRedux: subReduxReducer,
  ...otherStateSlices,
});

const store = createStore(rootReducer, applyMiddleware(subReduxMiddleware));

Using a subStore

import createSagaMiddleware from 'redux-saga';
import { delay, put, takeEvery } from 'redux-saga/effects';
import { actions, getId, getSubStore } from 'sub-redux';

// Create it by dispatching an init action:
const instance = getId();

const sagaMiddleware = createSagaMiddleware();

store.dispatch(
  actions.init({
    instance,
    initial: { count: 0 },
    reducer: (state, action) => {
      switch (action.type) {
        case 'INCREMENT':
          return { count: state.count + 1 };
        default:
          return state;
      }
    },
    middleware: [sagaMiddleware],
  }),
);

const task = sagaMiddleware.run(function*() {
  yield takeEvery('INCREMENT_LATER', function*() {
    yield delay(3000);
    yield put({ type: 'INCREMENT' });
  });
});

const subStore = getSubStore(instance, store);

// Use it
subStore.getState();
subStore.dispatch({ type: 'INCREMENT_LATER' });

//The above is equivalent to:
store.getState().subRedux[instance].state;
store.dispatch({ type: `SUB_REDUX/${instance}/INCREMENT_LATER` });

// Destroy it once you're done
task.cancel();
store.dispatch(actions.destroy({ instance }));

How it works

Dispatching the actions.init({ instance, initial, reducer, middleware }) action, two things happen:

  • Your initial state and the reducer are stored in the main store's state as subRedux[instance].state and subRedux[instance].reducer
  • The SubRedux middleware will take your provided middleware and build a chain out of it.

Once a subStore is initialised you can create a wrapper for it with getSubStore(instance, store). Calling getState() on the subStore returns you that state's store, and calling dispatch(action) on it will wrap that action and dispatch it against the main store. Whenever a SUB_REDUX/${n}/${action} is dispatched against the main store, subStore n will reduce and apply middlewares accordingly.

When you're finished with your subStore, dispatching actions.destroy({ instance }) against the main store will destroy it's state, reducer and middleware.

React usage

Higher up in your component tree:

import { Provider } from 'react-redux';

<Provider store={yourMainStore}>
  <YourApp />
</Provider>;

Your component in which you wish to create a subStore:

function MyComponent() {
  const sagaMiddleware = React.useMemo(
    () => createSagaMiddleware(),
    [], // Only ever create the one
  );

  const subStore = useSubRedux({
    initial,
    reducer,
    middlewares: [sagaMiddleware],
  });

  React.useEffect(() => {
    const task = sagaMiddleware.run(saga);
    return () => task.cancel(); // cancel on unmount
  }, [sagaMiddleware]);

  return (
    <Provider store={subStore}>
      <p>
        Any react-redux code below here in the React tree will use the subStore,
        rather than the main store.
      </p>
    </Provider>
  );
}

Accessing the main store in a context that is using a subStore

If you need to access the main store in a React subtree that uses a subStore, try the following:

import { ParentProvider } from 'sub-redux';

function MyComponentInContextOfSubStore() {
  return (
    <>
      <ThisComponentCanAccessTheSubStore />
      <ParentProvider>
        <ThisComponentCanAccessTheMainStore />
      </ParentProvider>
    </>
  );
}

ParentProvider accesses the subStore.parentStore, then renders a new Provider with parent store - anything below that will use the parent store.

Readme

Keywords

none

Package Sidebar

Install

npm i sub-redux

Weekly Downloads

1

Version

1.0.0-alpha.1

License

MIT

Unpacked Size

29.2 kB

Total Files

33

Last publish

Collaborators

  • adam1658