Getting Starting
In your Gatsby project run
npm install --save react-redux redux styled-componentsOr
yarn add redux react-redux styled-componentsStep 1
Create a new folder in your src/ directory called state Within this folder create the following files
src/
└── state/
├── reducers.js
├── actions.js
└── ReduxWrapper.jsStep 2
Create redux reducer
// reducers.js
import { combineReducers } from 'redux';
import { TOGGLE_THEME } from './actions';
const initialState = {
isDarkMode: false,
};
const theme = (state = initialState, action) => {
switch (action.type) {
case TOGGLE_THEME:
return {
...state,
isDarkMode: !state.isDarkMode,
};
default:
return state;
}
};
export default combineReducers({ theme });Step 3
create redux action to toggle current theme
// actions.js
export const TOGGLE_THEME = `TOGGLE_THEME`;
export const toggleTheme = () => ({ type: TOGGLE_THEME });Step 4
Create our Provider / ReduxWrapper Component Now we are able to go ahead a create the ReduxWrapper component
import { composeWithDevTools } from 'redux-devtools-extension';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';
import React from 'react';
const store = createStore(rootReducer, composeWithDevTools());
export default ({ element }) => <Provider store={store}>{element}</Provider>;composeWithDevTools() is optional but allows you to use the redux chrome extension that is very helpful for debugging
now that we have our ReduxWrapper component created, open up the ~gatsby-browser.js~ and the ~gatsby-ssr.js~ and add the following to both
export { default as wrapRootElement } from './src/state/ReduxWrapper';Step 5
Create our ToggleTheme button component
in the src/components/ create a new file named ToggleThemeButton.js
this is going to be a basic functional component that will allow us to connect to our state a trigger our reducer when we click the button
// components/ToggleThemeButton.js
import React from 'react';
import { connect } from 'react-redux';
import { toggleTheme } from '../state/actions';
const ToggleThemeButton = ({ toggleTheme }) => (
<button type="button" onClick={toggleTheme}>
toggle
</button>
);
const mapDispatchToProps = {
toggleTheme,
};
export default connect(null, mapDispatchToProps)(ToggleThemeButton);Step 6
making our redux state change our theme with styled-components
create a new file in your src/ directory called theme
first start by creating an object of shared styles such as font, accent colors, font weight, anything you like.
const sameStyles = { font: 'Roboto', accent: 'blue' };now create your light and dark objects, they must have the same keys but different values for this for work
export const light = { fg: 'black', bg: 'white', ...sameStyles };
export const dark = { fg: 'white', bg: 'black', ...sameStyles };
// we use the spread operator at the end of each object to add our same styles to eachnow in the same file we are going to create our HOC component
import { createGlobalStyle } from 'styled-components';
export const GlobalStyle = createGlobalStyle`
html,body {
background:${(props) => props.theme.bg};
color:${(props) => props.theme.fg};
}`;Step 7
connecting everything together! ok we’re almost there open up layout.js component and import everything from our theme
import { GlobalStyle, light, dark } from "../theme"
import { ThemeProvider } from "styled-components"
import { connect } from "react-redux"
const Layout = ({ children, isDarkMode }) => (
// ..
)
render={data => (
<ThemeProvider theme={isDarkMode ? light : dark}>
<GlobalStyle />
// ...
</ThemeProvider>
)}
const mapStateToProps = state => ({
isDarkMode: state.theme.isDarkMode,
})
export default connect(mapStateToProps)(Layout)Demo
And there you have it!
a fully functional dark-mode site using gatsby, redux, and styled-components