I'm building a Single App that will do SSR (server side rendering) and I'm using React + Redux.
I've just started to implement Redux in this app. It was previously built app using only React's useState
, useContext
etc.
The fact is that sometimes I need my app code to be aware of the environment that it's running, either ON_CLIENT
or ON_SERVER
, to skip some window.something
statement, for example.
Before Redux, I was doing the following:
index.js (this could be the index.js of my client bundle or my server bundle)
ReactDOM.render(
<App
ON_SERVER={false} // THIS IS TRUE ON SERVER CODE
ON_CLIENT={true} // THIS IS TRUE ON CLIENT CODE
... other stuff
/>
,document.getElementById('root')
);
App.js
...
const environment = {
ON_SERVER: props.ON_SERVER,
ON_CLIENT: props.ON_CLIENT
}
...
// PROVIDING IT USING REACT CONTEXT
return (
<EnvironmentContext.Provider value={environment}>
<MyComponents/>
</EnvironmentContext.Provider>
);
And then, inside some component, I can do this pattern:
SomeComponent.js
const {ON_CLIENT} = useContext(EnvironmentContext);
ON_CLIENT && window.something;
And I want to improve this pattern with Redux.
I want to keep this in the Redux store, so I can get rid of the EnvironmentContext
and access it with:
const {ON_CLIENT} = useSelector((state) => state.environment);
So I've thought of doing:
index.js
const store = createStore(rootReducer, {
environment: {
ON_CLIENT: true, // THIS IS TRUE ON CLIENT CODE
ON_SERVER: false // THIS IS TRUE ON SERVER CODE
}
});
But since I don't have a corresponding reducer for this piece of state (environment
), I got this error msg:
redux.js:319 Unexpected key "environment" found in preloadedState argument passed to createStore. Expected to find one of the known reducer keys instead: "auth", "appVersion", "siteData". Unexpected keys will be ignored.
NOTE: auth
, appVersion
and siteData
are pieces of state which I have corresponding reducers for.
Here is my rootReducer
:
const rootReducer = combineReducers({
auth: updateAuth,
appVersion: updateClientVersion,
siteData: updateSiteData
});
QUESTION
Can I have some piece of state that will not change, and therefore is not handled by any reducer? Or in this case I do need to set up some dummy reducer just to always return that same state? PS: It does the trick, but it feels wrong, though.
// NOTE: I will always preload this state, in the `createStore` call, so the state will never be undefined.
function returnEnvironment(state={}, action) {
return state;
}
const rootReducer = combineReducers({
auth: updateAuth,
appVersion: updateClientVersion,
siteData: updateSiteData,
environment: returnEnvironment
});
Does anybody have a better alternative to this?
I've looked at this discussion: https://github.com/reduxjs/redux/issues/1457
There are some suggestions to populate the global object, but I'd rather keep it all inside React
and Redux
.
PS: Sorry for the long question, but I wanted to make my use case as clear as I could, so somebody might have a better pattern.