Skip to content

Instantly share code, notes, and snippets.

@dthtien
Last active April 14, 2022 20:22
Show Gist options
  • Select an option

  • Save dthtien/d9ba9faabc73ce62069793b622243b6f to your computer and use it in GitHub Desktop.

Select an option

Save dthtien/d9ba9faabc73ce62069793b622243b6f to your computer and use it in GitHub Desktop.

Revisions

  1. dthtien revised this gist Oct 11, 2019. 2 changed files with 10 additions and 3 deletions.
    6 changes: 5 additions & 1 deletion createStore.js
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,13 @@
    //uttils/createStore.js
    import { combineReducers, applyMiddleware, createStore, compose } from "redux";
    import reducerRegistry from "./reducerRegistry";
    import createSagaMiddleware from "redux-saga";

    export const sagaMiddleware = createSagaMiddleware();

    const initialState = {};
    const enhancers = [];
    const middleware = [];
    const middleware = [sagaMiddleware];

    if (process.env.NODE_ENV === "development") {
    // eslint-disable-next-line no-underscore-dangle
    @@ -38,3 +41,4 @@ reducerRegistry.emitChange = reducers =>
    store.replaceReducer(combine(reducers));

    export default store;

    7 changes: 5 additions & 2 deletions reducerInjector.js
    Original file line number Diff line number Diff line change
    @@ -3,8 +3,9 @@ import React from "react";
    import { ReactReduxContext } from "react-redux";

    import reducerRegistry from "./reducerRegistry";
    import { sagaMiddleware } from "./createStore";

    export default ({ key, reducer }) => WrappedComponent => {
    export default ({ key, reducer, saga }) => WrappedComponent => {
    class ReducerInjector extends React.Component {
    static WrappedComponent = WrappedComponent;

    @@ -16,8 +17,10 @@ export default ({ key, reducer }) => WrappedComponent => {

    constructor(props, context) {
    super(props, context);

    reducerRegistry.register(key, reducer);
    if (saga) {
    sagaMiddleware.run(saga);
    }
    }

    render() {
  2. dthtien created this gist Oct 10, 2019.
    24 changes: 24 additions & 0 deletions SomeComponent.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    //views/SomeComponent/index.js
    import React from "react";
    import { connect } from "react-redux";
    import { compose } from "redux";
    import reducer, { reducerName as key } from "./reducer";
    // import reducerRegistry from "utils/reducerRegistry";
    import reducerInjector from "utils/reducerInjector";

    function SomeComponent() {
    const classes = useStyles();
    return <h1>The awesome component!</h1>
    }

    const withConnect = connect(
    null,
    null
    );

    const withReducer = reducerInjector({ key, reducer });

    export default compose(
    withConnect,
    withReducer
    )(SomeComponent);
    40 changes: 40 additions & 0 deletions createStore.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    //uttils/createStore.js
    import { combineReducers, applyMiddleware, createStore, compose } from "redux";
    import reducerRegistry from "./reducerRegistry";

    const initialState = {};
    const enhancers = [];
    const middleware = [];

    if (process.env.NODE_ENV === "development") {
    // eslint-disable-next-line no-underscore-dangle
    const devToolsExtension = window.__REDUX_DEVTOOLS_EXTENSION__;

    if (typeof devToolsExtension === "function") {
    enhancers.push(devToolsExtension());
    }
    }

    const composedEnhancers = compose(
    applyMiddleware(...middleware),
    ...enhancers
    );

    const reducer = combineReducers(reducerRegistry.reducers);
    const store = createStore(reducer, initialState, composedEnhancers);

    const combine = reducers => {
    const reducerNames = Object.keys(reducers);
    Object.keys(initialState).forEach(item => {
    if (reducerNames.indexOf(item) === -1) {
    reducers[item] = (state = null) => state;
    }
    });

    return combineReducers(reducers);
    };

    reducerRegistry.emitChange = reducers =>
    store.replaceReducer(combine(reducers));

    export default store;
    17 changes: 17 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    //index.js
    import React from "react";
    import ReactDOM from "react-dom";
    import { createBrowserHistory } from "history";
    import { Provider } from "react-redux";
    import store from "./utils/createStore";

    // core components
    import SomeComponent from "layouts/SomeComponent.js";
    const hist = createBrowserHistory();

    ReactDOM.render(
    <Provider store={store}>
    <SomeComponent/>
    </Provider>,
    document.getElementById("root")
    );
    29 changes: 29 additions & 0 deletions reducerInjector.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    //utils/reducerInjector.js
    import React from "react";
    import { ReactReduxContext } from "react-redux";

    import reducerRegistry from "./reducerRegistry";

    export default ({ key, reducer }) => WrappedComponent => {
    class ReducerInjector extends React.Component {
    static WrappedComponent = WrappedComponent;

    static contextType = ReactReduxContext;

    static displayName = `withReducer(${WrappedComponent.displayName ||
    WrappedComponent.name ||
    "Component"})`;

    constructor(props, context) {
    super(props, context);

    reducerRegistry.register(key, reducer);
    }

    render() {
    return <WrappedComponent {...this.props} />;
    }
    }

    return ReducerInjector;
    };
    26 changes: 26 additions & 0 deletions reducerRegistry.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    //utils/reducerRegistry.js
    export class ReducerRegistry {
    constructor() {
    this._emitChange = null;
    this._reducers = {};
    }

    get reducers() {
    return { ...this._reducers };
    }

    set emitChange(listener) {
    this._emitChange = listener;
    }

    register(name, reducer) {
    this._reducers = { ...this._reducers, [name]: reducer };
    if (this._emitChange) {
    this._emitChange(this.reducers);
    }
    }
    }

    const reducerRegistry = new ReducerRegistry();

    export default reducerRegistry;