skip to Main Content

WordFlix – Single Page App tutorial: Step 6 – Configure Redux and Apollo

Post Series: WordFlix – Super Powered Single Page App Tutorial

Step 6 – Starting Point

If you followed the previous steps of the tutorial, you should be able to continue here, but if you’re just jumping in or got lost in the last steps or just want to skip ahead, you can either check-out this branch of the Github repo or change directories to the “5” theme (wp-content/themes/5)

Redux & Apollo

Redux is a Client side state manager that plays very nice with React.

Instead of explaining Redux myself, this is straight from redux.js.org:

Redux is a predictable state container for JavaScript apps.

It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. On top of that, it provides a great developer experience, such as live code editing combined with a time traveling debugger.

You can use Redux together with React, or with any other view library.
It is tiny (2kB, including dependencies).

Any state changes that are made in our app can easily be stored in the Redux store, and components can subscribe to relevant parts of the Redux store and automatically re-render when relevant changes to the app are made. 

Apollo, which we’ll be using to manage the data we fetch via GraphQL queries, uses Redux to manage queries and associated data for our App.

Configure the Redux Store & Apollo

Let’s create a new file at “/app/src/state/index.js”

This will be the entry point for state management (the Redux store).

Import Dependencies

Inside “/state/index.js” let’s import our dependencies:

import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import ApolloClient, { createNetworkInterface } from  'apollo-client';
import createLogger from 'redux-logger';
import thunk from 'redux-thunk';
import { routerReducer } from 'react-router-redux';

Configure ApolloClient

Next, let’s configure our ApolloClient, and export it for use outside of this file. This tells Apollo where our GraphQL endpoint is. In our case, it’s our Local by Flywheel WordPress site. (learn more about configuring Apollo)

export const client = new ApolloClient({
  networkInterface: createNetworkInterface({ uri: 'http://graphql-workshop.dev/graphql'})
});

Create our rootReducer

Next, lets configure our rootReducer for Redux. This creates the root shape of our Redux state tree. So, at the base of our Redux state we will have an Apollo entry point, and a Routing entry point. (learn more about Redux reducers):

const rootReducer = combineReducers({
  apollo: client.reducer(),
  routing: routerReducer,
});

Instantiate Logger Middleware

const loggerMiddleware = createLogger();

This is helpful during development as it will output a console.log message for every Redux action that occurs. (learn more about Redux logger)

Configure the Store

Here we configure the store, which creates the Redux store and adds any middleware we’re passing it, such as our LoggerMiddleware

export function configureStore(initialState = {}) {
  return createStore(rootReducer, initialState, compose(
    applyMiddleware(thunk, loggerMiddleware),
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
  ));
}

This is all the code we need to create our Redux store.

Next, we need to hook our App up to the Redux store.

Connect our App to the Redux store with Apollo Provider

Back in our “/src/index.js” file, we’ll setup our App to be connected to the Redux store.

Import dependencies

Let’s add the imports we’ll need for this file. Up in the imports section, let’s add the following:

import { client, configureStore } from './state';
import { syncHistoryWithStore } from 'react-router-redux';
import { ApolloProvider } from 'react-apollo';

Then below all of our imports, we’ll instantiate the store and the app history:

const store = configureStore();
const history = syncHistoryWithStore(browserHistory, store);

Now let’s update our App component to use the ApolloProvider component, which effectively connects the app to the Redux store.

class App extends Component {
  render() {
    return(
      <ApolloProvider store={store} client={client}>
        <Router history={history} render={applyRouterMiddleware(useScroll())}>
          <Route component={PageLayout} >
            <Route path="/movies" component={MoviesPage} />
            <Route path="/movies/:movieId" component={MoviePage} />
          </Route>
          <Route path="*" component={HomePage} />
        </Router>
      </ApolloProvider>
    )
  }
}

At this point, our App is now connected to Redux.

When running the app in dev mode (npm run start) you can open the Redux Dev Tools and see how actions, such as route changes, are logged in Redux, and you can even time travel through state changes!

Below is a screenshot of the App in it’s current state, and using Redux Dev Tools to monitor Router Location Changes, then using Time Travel to step through the changes.

Leave a Reply

Share This
Back To Top