npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-store-manager

v0.1.9

Published

Declaratively code-split your redux store and make containers own entire redux flow using redux-store-manager

Downloads

6

Readme

redux-store-manager

Declaratively code-split your redux store and make containers own entire redux flow using redux-store-manager

Installation

yarn add redux-store-manager

Problem

  1. rootReducer is traditionally created manually using combineReducers and this makes code-splitting reducers based on how widgets consuming their data are loaded(whether they are in the main bundle or on-demand bundles) hard.
  2. Bundler cant tree-shake or dead code eliminate the rootReducer to not include reducers whose data is not consumed by any container components

Solution

  1. Let the containers that are going to consume the data stored by a reducer and trigger actions take responsibility of adding a reducer to the store. This makes the container owning the entire redux flow by linking
    • Actions as component props via mapDispatchToProps
    • Reducer responsible for updating the data via storeManager.registerReduers
    • Data as component props via mapStateToProps
  2. Use the redux store's replaceReducer API whatever reducers are registered when an on-demand chunk loads the store gets refreshed with the new rootReducer.

Documentation

storeManager is a singleton that has the following methods

1. storeManager.registerReducers(reducerMap)

  • reducerMap is an object with reducer namespaces as keys and reducer definitions as values (similar to the object you pass to combineReducers).
  • This method is used in container components to register the reducer on the store to be created.

2. storeManager.createStore(initialState, storeEnhancer)

  • createStore method takes the same arguments that createStore function of redux library without the rootReducer argument.
  • createStore is called to pass the store prop to component.
  • both the initialState, storeEnhancer are optional.

3. storeManager.refreshStore()

  • refreshStore is called when the on-demand build chunk is loaded, to replace the rootReducer of the store.
  • The refreshed store will include the registered reducers in the on-demand chunk that was just loaded.

Example of usage in a React app

Root.js

import {Provider} from 'react-redux';
import storeManager from 'redux-store-manager';
import App from './containers/AppContainer';

export default function Root() {
  return (
    // creates store with all the reducers registered by container components
    <Provider store={storeManager.createStore(initialState, storeEnhancer)}>
      <App>
    </Provider>
  )
}


/* ReactDOM.render(<Root/>, document.getElementById('root')); */

App.js

import React, {Component} from 'react';
import {withRefreshedStore} from 'redux-store-manager';
import SimpleWidgetContainer from './containers/SimpleWidgetContainer';

export default class App extends React {
  state = {
    OnDemandWidgetContainer: null
  };
  componentWillMount() {
    // when loading a widget on-demand along with the component codebase the reducers are also
    withRefreshedStore(import('./containers/SimpleWidgetContainer')).then((module) => {
      this.setState({OnDemandWidgetContainer: module.default});
    });
  }
  render() {
    const {OnDemandWidgetContainer} = this.state;

    return (
      <>
        <SimpleWidgetContainer />
        {OnDemandWidgetContainer ? <OnDemandWidgetContainer/> : null}
      </>
    );
  }
}

SimpleWidgetContainer.js

import storeManager from 'react-store-manager';
import {connect} from 'react-redux';
import SimpleDemandWidget from '../components/SimpleWidget';
import simpleDemandWidgetReducer from '../reducers/simopleWidgetReducer';
import {getSimpleWidgetData} from '../actions';

// reducer and its initialStatw will be added to the store.
storeManager.registerReducers({
  simpleWidgetData: simpleWidgetDataReducer
});

const mapStateToProps = (state) => ({ simpleWidgetData: state.simpleWidgetData });
const mapDispatchToProps = { getSimpleWidgetData };

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(OnDemandWidget);

OnDemandWidgetContainer.js

import storeManager from 'react-store-manager';
import {connect} from 'react-redux';
import OnDemandWidget from '../components/OnDemandWidget';
import onDemandWidgetReducer from '../reducers/onDemandWidgetReducer';
import {getOnDemandWidgetData} from '../actions';

/*
 * reducers registered in on-demand chunks will be added to redux store
 * only when the on-demand chunk is loaded
 */
storeManager.registerReducers({
  onDemandWidgetData: onDemandWidgetDataReducer
});

const mapStateToProps = (state) => ({ onDemandWidgetData: state.onDemandWidgetData });
const mapDispatchToProps = { getOnDemandWidgetData };

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(OnDemandWidget);