I recently undertook the task of moving an old React project into the Gatsby frontend framework. Mostly this was to take advantage of Gatsby serving React as static HTML files and resolving many of the SEO issues faced by pure React applications.
One of the issues I faced was exactly how to move across my existing Redux store into Gatsby. Gatsby uses it’s own pre-configured Webpack to create development and production builds and hooking up Redux into this process was far simpler than first thought… contrary to a lot of muddled guides online. Let’s run through the process in a few simple steps:
Step 1
First let’s install redux
, react-redux
and gatsby-plugin-react-redux
(with a package manager of your choice - I’m using NPM):
npm i --save gatsby-plugin-react-redux react-redux redux
Step 2:
In our src
folder, create a new folder called: state
and inside the state
folder create a folder named: reducers
.
Inside reducers we will add any reducer.js files we want and combine them into one store.
Create a reducer test-reducer.js
inside the reducers
folder with contents:
const initialState = {
aString: ‘Test string’,
};
const testReducer = (state = initialState) => {
// Create dispatch actions here
return state;
};
export default testReducer;
Then create another file inside the reducers
folder called index.js
. This file will combine any and all reducers we add to the reducers folder like so:
import { combineReducers } from 'redux';
// Import other reducers
import testReducer from ‘./test-reducer';
// Combine all reducers
const rootReducer = combineReducers({
testReducer,
});
export default rootReducer;
Next we need to create our redux store. In the state
folder we created add a new file called: createStore.js
- with the following contents:
import { createStore } from 'redux';
// Import the Root Reducer
import rootReducer from './reducers/index';
// preloadedState will be passed in by the plugin
export default preloadedState => {
return createStore(rootReducer, preloadedState);
};
We now have an operational redux store that we can access in our build.
Step 3
In our gatsby-config.js
file add the following plugin config. You will notice that we’re referencing the createStore.js
that we created in Step 2:
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-react-redux`,
options: {
// [required] - path to your createStore module
pathToCreateStoreModule: './src/state/createStore',
// [optional] - options passed to `serialize-javascript`
// info: https://github.com/yahoo/serialize-javascript#options
// will be merged with these defaults:
serialize: {
space: 0,
// if `isJSON` is set to `false`, `eval` is used to deserialize redux state,
// otherwise `JSON.parse` is used
isJSON: true,
unsafe: false,
ignoreFunction: true,
},
// [optional] - if true will clean up after itself on the client, default:
cleanupOnClient: true,
// [optional] - name of key on `window` where serialized state will be stored, default:
windowKey: '__PRELOADED_STATE__',
},
},
]
}
Unlike standard React builds we do not need to wrap our application/components with a react-redux { Provider }. Normally the Provider component gives our application/components access to our Redux store, but this is handled by our gatsby-plugin-react-redux plugin.
Step 4
We can now access our Redux store from any of our React components as per:
import { useSelector, useDispatch } from 'react-redux';
const TestComponent = () => {
// React Redux hooks
const dispatch = useDispatch();
const query = useSelector((state) => state.testReducer);
return (
<p>{query.aString}</p>
);
};
export default TestComponent;
Happy Gatsby-Reduxing!