Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux state is undefined in mapStateToProps with two stores

I have two react apps which each has it's own redux store (inside ASP.Net Core, but I don't think that's relevant). I found that I had quite a lot of duplicate code between the two apps so I made a Ui.Common Project for the shared code between the two projects. In that scope I introduced a commonStore that each of the two apps uses as well as their own store. As per the docs I initialize the commonStore on it's own React-Context and the connect calls reference that same context when the commonStore is required. For the initialization of the stores I do:

const store = ReduxStore.configureStore(history);
const commonStore = CommonStore.configureStore();
ReactDOM.render(
    <Provider store={store}>
        <Provider store={commonStore} context={CommonContext}>
            <ConnectedRouter history={history} children={routes} />
        </Provider>
    </Provider>,
    document.getElementById('react-app')
);

Config for the CommonStore

public configureStore() {
    const windowIfDefined = typeof window === 'undefined' ? null : window as any;
    // If devTools is installed, connect to it
    const devToolsExtension = windowIfDefined && windowIfDefined.__REDUX_DEVTOOLS_EXTENSION__ as () => StoreEnhancer;
    const createStoreWithMiddleware = compose(devToolsExtension ? devToolsExtension() : <S>(next: StoreEnhancerStoreCreator<S>) => next)(createStore);
    const store = createStoreWithMiddleware(rootReducer()) as Store<CommonAppState>;
    return store;
}

And these are my "helper" methods for interacting with the commonStore:

export function rootReducer(): Reducer<CommonAppState> {
    return combineReducers<CommonAppState>({
        app: appReducer,
        userSettings: userSettingsReducer
    });
}

export const CommonContext = React.createContext<ReactReduxContextValue>(undefined);

/** A connect wrapper to connect specifically to the common redux store. */
export function commonConnect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?: ConnectOptions) {
    if (!options) {
        options = {};
    }
    options.context = CommonContext;
    return connect(mapStateToProps, mapDispatchToProps, mergeProps, options);
}

In one of the apps (Ui.WebApp) this works as expected, the two stores work independently and everything is nice.

In the second app (Ui.Management) the commonConnect doesn't seem to work correctly. In the redux dev-tools I can see that the store is there, gets initialized and has a default initial state. Also, the dispatches (from mapDispatchToProps) I execute on the store are there and update the store accordingly. But in every single mapStateToProps the state is always undefined.

Most of the components consuming the commonStore actually "live" in Ui.Common and as they work in Ui.WebApp but not in Ui.Management, the problem most likely is not located within the Ui.Common project.

The two partial reducers definitely have their default set, as otherwise it wouldn't work in any of the two apps.

like image 277
Nasto Avatar asked Jun 04 '19 09:06

Nasto


People also ask

Why is state undefined React Redux?

When used with function calls, it returns undefined if the given function does not exist. This results in shorter and simpler expressions when accessing chained properties when the possibility exists that a reference may be missing.

What does mapStateToProps do in Redux?

As the first argument passed in to connect , mapStateToProps is used for selecting the part of the data from the store that the connected component needs. It's frequently referred to as just mapState for short. It is called every time the store state changes.

Should I keep all component's state in Redux store?

Some users prefer to keep every single piece of data in Redux, to maintain a fully serializable and controlled version of their application at all times. Others prefer to keep non-critical or UI state, such as “is this dropdown currently open”, inside a component's internal state. Using local component state is fine.

What is mapStateToProps and mapDispatchToProps in React Redux?

The mapStateToProps and mapDispatchToProps deals with your Redux store's state and dispatch , respectively. state and dispatch will be supplied to your mapStateToProps or mapDispatchToProps functions as the first argument.


1 Answers

Think about creating an extendible store to aggregate the common store with the custom one. Try implementing a function that takes custom reducers as params and aggregate them with the commons. I tried a similar solution and it work easily instantiating only one rect-redux Provider. Something like:

const createMyStore = (customReducers) => createStore(
  combineReducers({
    common: commonReducer,
    ...customReducers
  });
);

Tell me if the solution works fine for you.

like image 61
Andrea - codemillers.com Avatar answered Sep 23 '22 13:09

Andrea - codemillers.com