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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With