Setting up Redux with GatsbyJS V2
redux makes managing react state efficient and fun
Redux allows us to manage state across multiple components without having to pass props to between components. If you have a simple application, I wouldn’t bother using Redux unless you have a specific use for it. For example, in this tutorial I use redux to redirect the user back to the link where they started their authentication from.
Setup
npm install react-redux redux
yarn add react-redux redux
Actions
For this example we are just going to add only one action to our actions file. Create a new file for your actions named index.js located in src/actions
export const setCallbackLink = callbackLink => ({ type: 'SET_CALLBACK_LINK', callbackLink });
Store
This file will be named createStore.js located in src/state
import { createStore as reduxCreateStore } from 'redux';
const reducer = (state, action) => {
if (action.type === 'SET_CALLBACK_LINK') {
return Object.assign({}, state, { callbackLink: action.callbackLink });
}
return state;
};
const initialState = {
callbackLink: '/',
};
const createStore = () => reduxCreateStore(reducer, initialState)
export default createStore;
Wrap with Provider
Create a new file at the root of your project named wrap-with-provider.js. This file will be imported in our gatsby-browser and gatsby-ssr and wrapped around our entire application allowing any component to access our store.
import React from 'react';
import { Provider } from 'react-redux';
import createStore from './src/state/createStore';
const { store } = createStore();
export default ({ element }) => (
<Provider store={store}>
{element}
</Provider>
);
Gatsby SSR and Browser
Our Gatsby SSR and Browser files will be identical. Create a gatsby-ssr.js and gatsby-browser.js file at the root of your projects directory.
import wrapWithProvider from "./wrap-with-provider"
export const wrapRootElement = wrapWithProvider
Accessing Store in Client
You can wrap any component with a Redux connect in order to be able to access your store from anywhere. In this example we inject the callbackLink using mapDispatchToProps. Once we do that we are able to access that variable inside of props.
import React, { Component } from 'react';
import loading from 'assets/images/loading.svg';
import { navigate } from 'gatsby';
import { handleAuthentication } from 'auth/Auth';
import { connect } from 'react-redux';
import { setCallbackLink } from '../actions';
const mapStateToProps = ({ callbackLink }) => ({ callbackLink });
const mapDispatchToProps = dispatch => ({
setCallbackLink: callbackLink => dispatch(setCallbackLink(callbackLink)),
});
class Callback extends Component {
componentDidMount() {
const { callbackLink } = this.props;
handleAuthentication();
setTimeout(() => {
if (callbackLink === '/') {
navigate('/search');
} else {
navigate(callbackLink);
}
}, 1500);
}
render() {
return (
<div style={{
position: 'absolute',
display: 'flex',
justifyContent: 'center',
height: '98vh',
width: '98vw',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'white',
}}
>
<img src={loading} alt="loading" />
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Callback);