A Beginner's Guide to Redux

A Beginner's Guide to Redux

In this article, you’ll learn how to create a simple app using React and Redux, and how to secure your app using Okta for authentication.

In this article, you’ll learn how to create a simple app using React and Redux, and how to secure your app using Okta for authentication.

React has gained a lot of popularity over the last few years, and Redux is a term often heard in combination with it. While technically separate concepts, they do work quite nicely together. React is a component-based framework, often used to create a Single-Page App (SPA), but can also be used to add any amount of independent components to any website. Redux is a state management system with a great set of dev tools useful for debugging.

When To Use Redux With React

React components can accept properties as well as manage their own state. Redux provides a global app state that any component can link into.

Redux is not something that every app needs. While it has its advantages, it can also add quite a bit of complexity. There is also a myriad of variants on redux to try to simplify it, and there are countless ways to architect the files needed. Generally, redux should not be added to any project without a good understanding of why you need it. Here are a few examples of what React-Redux can give you over a vanilla React approach:

  • Redux gives you a global state. This can be helpful when you have deeply nested components that need to share the same state. Rather than passing unrelated properties down the component tree, you can simply access the Redux store.
  • Debugging can be much simpler.
    You can rewind the data to specific points to see the state of the app before or after any given action.It’s possible to log all actions a user took to get to a specific point (say an app crash, for example).Hot-reloading is more reliable if the state is stored outside the component itself.* Business logic can be moved into the Redux actions to separate business logic from components.
Create a Search App in React

This will be a pretty simplified example, but hopefully gives you an idea what some of the benefits are of using Redux in a React app. TV Maze provides an open API for querying TV shows. I’ll show you how to create an app that lets you search through TV shows and display details for each show.

Assuming you have Node installed on your system, you’ll next need to make sure you have yarn and create-react-app in order to complete this tutorial. You can install both by using the following command line:

npm i -g [email protected] [email protected]


Now you can quickly bootstrap a new React app with the following command:

create-react-app react-redux


That will create a new directory called react-redux, add some files for a skeleton project, and install all the dependencies you need to get up and running. Now you can start the app with the following:

cd react-redux
yarn start


Set Up Redux for Your React App

First, you’ll want to install the dependencies you’ll need. Use the following command:

yarn add [email protected] [email protected] [email protected]


Redux Actions

Redux has a few moving parts. You’ll need actions that you can dispatch to tell redux you want to perform some action. Each action should have a type, as well as some sort of payload. Create a new file, src/actions.js with the following code:

export const SEARCH_SHOWS = 'SEARCH_SHOWS';
export const SELECT_SHOW = 'SELECT_SHOW';

export const searchShows = term => async dispatch => {
  const url = new URL('https://api.tvmaze.com/search/shows');
  url.searchParams.set('q', term);

  const response = await fetch(url);
  const results = await response.json();

  dispatch({ type: SEARCH_SHOWS, results, term });
};

export const selectShow = (id = null) => ({ type: SELECT_SHOW, id });


You’ll be using redux-thunk, which allows us to handle actions asynchronously. In the example above, selectShow is a simple, synchronous action, which just selects a show using a given ID. On the other hand, searchShows is async, so instead of returning a JSON object, it returns a function that accepts a dispatch function. When the action is finished, instead of returning the payload, you pass it into the dispatch function.

Redux Reducers

The next thing you’ll need is a reducer to tell redux how an action should affect the data store. Reducers should be pure functions that return a new state object rather than mutating the original state. Create a new file, src/reducers.js with the following code:

import { combineReducers } from 'redux';
import { SEARCH_SHOWS, SELECT_SHOW } from './actions';

const initialShowState = {
  detail: {},
  search: {},
  selected: null,
};

const shows = (state = initialShowState, action) => {
  switch (action.type) {
    case SEARCH_SHOWS:
      const detail = { ...state.detail };
      action.results.forEach(({ show }) => {
        detail[show.id] = show;
      });

      return {
        detail,
        search: {
          ...state.search,
          [action.term]: action.results.map(({ show }) => show.id),
        },
      };
    case SELECT_SHOW:
      return {
        ...state,
        selected: action.id,
      };
    default:
      return state;
  }
};

export default combineReducers({
  shows,
});


In this example, you have a single shows reducer, and its state will be stored in state.shows. It’s common to separate logic into different sections using this method, combining them using combineReducers.

The reducer takes the current state object. If the state is undefined, which will be true during initialization, then you will want to provide a default, or initial, state. You then need to look at the type of the action to determine what you should do with the data.

Here, you have the SEARCH_SHOWS action, which will update the detail cache for each object and store a list of search results by ID. The data that TV Maze returns looks like:

[
  { score: 14.200962, show: { id: 139, name: "Girls", /* ... */ } },
  { score: 13.4214735, show: { id: 23542, name: "Good Girls", /* ... */ } },
  // ...
]


This was simplified in the reducer, so the detail for each show is stored by ID, and the search results are just an array of IDs stored by the search term. This will cut down on memory because you won’t need a separate copy of each show detail for each search term.

For the SELECT_SHOW action, you just set selected to the ID of the show.

If you don’t recognize the action, you should just return the state as it is currently. This is important so that the state doesn’t become undefined.

Redux Store

Now that you have your reducer, you can create the store. This is made easy by redux-starter-kit. A lot of the boilerplate has been moved into that, making it customizable but with some very reasonable defaults (such as including Redux Thunk to handle async actions and hooking into Redux Devtools for better debugging). Create a new file src/store.js with the following code:

import { configureStore } from 'redux-starter-kit';
import reducer from './reducers';

export default configureStore({ reducer });


React Redux

React and Redux are really two separate concepts. In order to get Redux working with your app, you’ll need to use react-redux to bridge the two pieces (strictly speaking, it’s not 100% necessary to use react-redux, but it makes things a lot simpler). Replace the contents of src/App.js with the following:

import React from 'react';

import { Provider } from 'react-redux';
import store from './store';

const App = () => (
  <div>TODO: Build TV search components</div>
);

export default () => (
  <Provider store={store}>
    <App />
  </Provider>
);


The Provider component has access to the store and passes it along to child components using context. A component, later on, can access the store, even if it is deeply nested in the React tree.

Create the Search and Detail Components for Your React App

Before you get started building out the components, I’ll have you install a few more dependencies.

  • Redux gives you a global state. This can be helpful when you have deeply nested components that need to share the same state. Rather than passing unrelated properties down the component tree, you can simply access the Redux store.
  • Debugging can be much simpler.
    You can rewind the data to specific points to see the state of the app before or after any given action.It’s possible to log all actions a user took to get to a specific point (say an app crash, for example).Hot-reloading is more reliable if the state is stored outside the component itself.* Business logic can be moved into the Redux actions to separate business logic from components.

Install these with the following command:

yarn add [email protected] [email protected] [email protected]


Then, in src/index.js, you’ll need to add required CSS imports. You also will no longer need the default CSS from create-react-app. Replace this line:

import './index.css';


with the following two lines:

import 'bootstrap/dist/css/bootstrap.min.css';
import 'react-bootstrap-typeahead/css/Typeahead.css';


Search Component

Create a new file src/Search.js containing the following:

import React, { useState } from 'react';
import { connect } from 'react-redux';
import { AsyncTypeahead } from 'react-bootstrap-typeahead';

import { searchShows, selectShow } from './actions';

const Search = ({ shows, fetchShows, selectShow, onChange }) => {
  const [value, setValue] = useState('');
  const options = (shows.search[value] || []).map(id => shows.detail[id]);

  return (
    <AsyncTypeahead
      autoFocus
      labelKey="name"
      filterBy={() => true}
      onSearch={term => {
        fetchShows(term);
        setValue(term);
      }}
      onChange={selectShow}
      placeholder="Search for a TV show..."
      isLoading={Boolean(value) && !shows.search[value]}
      options={options}
    />
  );
};

const mapStateToProps = state => ({
  shows: state.shows,
});

const mapDispatchToProps = dispatch => ({
  fetchShows: value => dispatch(searchShows(value)),
  selectShow: ([show]) => dispatch(selectShow(show && show.id)),
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Search);


React-Redux’s connect function is the glue that connects a component to the Redux store. It requires a mapStateToProps function that will transform the Redux state into properties that will be passed to your component. In this case, it is getting the shows subset of the store, which contains the detail, search, and selected you set up earlier.

The connect function also takes an optional mapDispatchToProps function, which allows your component to receive function properties that will dispatch actions. Here, you’re getting a function fetchShows to search for shows with the search term you pass in, and another function selectShow that will tell redux which show you’ve selected.

The AsyncTypeahead component from react-bootstrap-typeahead gives you a few hooks to trigger a search or select an option. If the user has started typing but the redux store doesn’t have any results yet (not even an empty array), then this adds a loading icon to the search box.

Detail Component

Next, to display the details of the selected show, create a new file src/Detail.js containing the following:

import React from 'react';
import ReactHtmlParser from 'react-html-parser';
import { connect } from 'react-redux';

const Detail = ({ show }) =>
  show ? (
    <div className="media">
      {show.image && (
        <img
          className="align-self-start mr-3"
          width={200}
          src={show.image.original}
          alt={show.name}
        />
      )}
      <div className="media-body">
        <h5 className="mt-0">
          {show.name}
          {show.network && <small className="ml-2">{show.network.name}</small>}
        </h5>
        {ReactHtmlParser(show.summary)}
      </div>
    </div>
  ) : (
    <div>Select a show to view detail</div>
  );

const mapStateToProps = ({ shows }) => ({
  show: shows.detail[shows.selected],
});

export default connect(mapStateToProps)(Detail);


If there is no show selected, you’ll get a simple message to select a show first. Since this is connected to the redux store, you can get the detail for a selected show with shows.detail[shows.selected], which will be undefined if there is no show selected. Once you’ve selected one, you’ll get the detail passed in as the show prop. In that case, you can show the artwork, name, network, and summary for the show. There’s a lot more information contained in the details, so you can display quite a bit more information if you want to play around with the detail page some more.

Add the Components to Your React App

Now that you’ve created the Search and Detail components, you can tie them into your app. Back in src/App.js, replace the placeholder App functional component (containing the TODO) with the following:

  <div className="m-3">
    <Search />
    <div className="my-3">
      <Detail />
    </div>
  </div>


You’ll also need to make sure to import those components at the top of the file:

import Search from './Search';
import Detail from './Detail';


For reference, here’s the full src/App.js file after these changes:

import React from 'react';

import { Provider } from 'react-redux';
import store from './store';

import Search from './Search';
import Detail from './Detail';

const App = () => (
  <div className="m-3">
    <Search />
    <div className="my-3">
      <Detail />
    </div>
  </div>
);

export default () => (
  <Provider store={store}>
    <App />
  </Provider>
);


Profit

You should now have a fully functional web app where you can search for TV shows and get some details.

If you install the Redux DevTools Extension you’ll also be able to replay actions, view the data in the store, and much more.

Add User Authentication To Your React Redux App

Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. If you don’t already have one, sign up for a forever-free developer account. Log in to your developer console, navigate to Applications, then click Add Application. Select Single-Page App, then click Next.

Since Create React App runs on port 3000 by default, you should add that as a Base URI and Login Redirect URI. Your settings should look like the following:

Click Done to save your app, then copy your Client ID and paste it as a variable into a file called .env.local in the root of your project. This will allow you to access the file in your code without needing to store credentials in source control. You’ll also need to add your organization URL (without the -admin suffix). Environment variables (other than NODE_ENV) need to start with REACT_APP_ in order for Create React App to read them, so the file should end up looking like this:

REACT_APP_OKTA_ORG_URL=https://{yourOktaDomain}
REACT_APP_OKTA_CLIENT_ID={yourClientId}


You may need to restart your server before it will recognize these changes. You can find the running instance and then hit ctrl-c to close it. Then run it again with yarn start.

The easiest way to add Authentication with Okta to a React app is to use Okta’s React SDK. You’ll also need to add routes, which can be done using React Router. Go ahead and add these dependencies:

yarn add @okta/[email protected] [email protected]


You’ll need to make some changes to src/App.js now. Here’s what the final output should be, but I’ll go over what the differences are:

import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { Security, ImplicitCallback, withAuth } from '@okta/okta-react';

import { Provider } from 'react-redux';
import store from './store';

import Search from './Search';
import Detail from './Detail';

const App = withAuth(({ auth }) => {
  const [authenticated, setAuthenticated] = useState(null);

  useEffect(() => {
    auth.isAuthenticated().then(isAuthenticated => {
      if (isAuthenticated !== authenticated) {
        setAuthenticated(isAuthenticated);
      }
    });
  });

  return (
    <div className="m-3">
      {authenticated ? (
        <>
          <div className="mb-3">
            <button className="btn btn-primary" onClick={() => auth.logout()}>
              Logout
            </button>
          </div>
          <Search />
          <div className="my-3">
            <Detail />
          </div>
        </>
      ) : authenticated === null ? (
        <h4>Loading...</h4>
      ) : (
        <button className="btn btn-primary" onClick={() => auth.login()}>
          Login to search TV Shows
        </button>
      )}
    </div>
  );
});

export default () => (
  <Provider store={store}>
    <Router>
      <Security
        issuer={`${process.env.REACT_APP_OKTA_ORG_URL}/oauth2/default`}
        client_id={process.env.REACT_APP_OKTA_CLIENT_ID}
        redirect_uri={`${window.location.origin}/implicit/callback`}
      >
        <Route path="/" exact component={App} />
        <Route path="/implicit/callback" component={ImplicitCallback} />
      </Security>
    </Router>
  </Provider>
);


The main App functional component now uses a piece of state to track whether or not a user is authenticated. Whenever the component renders, an effect checks whether or not authentication has changed. This makes sure that if a user logs in or out the component will properly update. Because it’s wrapped with Okta’s withAuth, it can now access the auth prop in order to check for authentication.

The main portion of the return statement in App now renders the same thing it previously did, but only if the user is authenticated. It also adds a Logout button in that case. If authenticated is null, that means Okta hasn’t yet told you whether or not you’re authenticated, so it just shows a simple “Loading” text. Finally, if you’re not authenticated, it just shows a login button that will redirect you to your Okta org to sign in.

The default export now wraps the app with React Router and Okta, as well as Redux. This now allows you to use withAuth to pull authentication information out of context. It also uses Okta and React Router to decide whether to render App or redirect you to log in or out.

Should I choose Redux or Flux for ReactJS?

Having a similar state, action and unidirectional data flow, the Flux and Redux do have some differences.

An intro to Redux and how state is updated in a Redux application

An intro to Redux and how state is updated in a Redux application

I started learning Redux a few days back and it was an overwhelming concept for me at the start. After polishing my skills in ReactJS by making a&nbsp;<a href="https://github.com/aimenbatool/my-reads" target="_blank">personal book reading application</a>, I headed towards Redux to learn more about it.

I started learning Redux a few days back and it was an overwhelming concept for me at the start. After polishing my skills in ReactJS by making a personal book reading application, I headed towards Redux to learn more about it.

Today, I’m going to share a few core Redux concepts without using any view library (React or Angular). This is a kind of a personal note for future reference but it can help others as well.

Let’s dig in together!

What is Redux?

Redux is an open-source library to improve the predictability of the state in a JavaScript application. It is an independent library. It is commonly used with other libraries like React and Angular for better state management of the application. Redux was created by Dan Abramov in 2015 to handle complex state management in an efficient way.


When an application grows larger it becomes harder to manage the state and debug for issues. It becomes a challenge to track when and where the state is changed and where the changes need to be reflected. Sometimes a user input triggers some API call which updates some model. That model in turn updates some state or maybe the other model and so on.

In such a situation it becomes grinding to track the state changes. It happens mainly because there is no defined rule to update a state and state can be changed from anywhere inside the application.

Redux tries to solve this issue by providing a few simple rules to update the state to keep it predictable. Those rules are the building blocks of Redux.

Redux Store:

As we discussed earlier, the main purpose of Redux is to provide predictable state management in our applications. Redux achieves this by having a single source of truth, that is a single state tree. The state tree is a simple JavaScript object which holds the whole state of our application. There are only a few ways to interact with the state. And this makes it easy for us to debug or track our state.


We now have only one main state which occupies the whole state of the application located at a single location. Any changes made into the state tree are reflected in the whole application because this is the only source of data for the app. And, this is the first fundamental principle of Redux.

Rule #1 — Single source of truth

The state of your whole application is stored in an object tree within a single store. — Official docs

The ways you can interact with a state tree are:

  • Getting the state
  • Listening to the changes in the state
  • Updating the state

store is a single unit that holds the state tree and the methods to interact with the state tree. There is no other way to interact with a state inside the store except through these given methods.

Let’s talk about the methods a store gives us to interact with the state.

  • getState() — Returns the current state of the application.
  • dispatch(action) — The only way to update a state is by dispatching an action and dispatch(action) serves the purpose. We will talk more in detail in a bit.
  • subscribe(listener) — The purpose of this method is to listen for the state changes. Every time a state is changed, it will be called and will return the updated state.
  • replaceReducer(nextReducer) — Replaces the reducer currently used by the store to calculate the state.

Now when we have a store which contains a state tree and a few ways to interact with the state, how can we update application state?

Updating state in the application:

The only way to update a state is to dispatch an action. This is the 2nd rule.


Rule #2 — State is read-only

An action is a plain JavaScript object to keep track of the specific event taking place in the application. What makes it special is a ‘type’ property which is a necessary part of it.


{
  type: "ADD_BOOK_TO_THE_CART"
}

The main purpose of this property is to let Redux know about the event taking place. This type should be descriptive about the action. Along with the ‘type’ property, it can have other information about the event taking place.

Actions can have as much information as you want. It is a good practice to provide less and necessary information — preferably an id or any unique identifier wherever possible.

Here we have an action to add a book to the cart.

{
    type: 'ADD_BOOK_TO_THE_CART',
    bookId: 10, 
}

Once we define our action we pass it to the dispatcher. store.dispatch() is a function provided by the library which accepts an action to perform an action against the state. Redux restricts updating the state to this method only.

store.dispatch({
    type: 'ADD_BOOK_TO_THE_CART',
    bookId: 10,
})

This strict way of updating the state ensures that the state can not be changed directly either by view or any network callback. The only way to update a state is by defining the action and then dispatching it. Remember that actions are plain JavaScript objects. Actions can be logged, serialized, and replayed for debugging purposes.

We now have a store, a state, and an action in our app to perform some tasks against the state. Now we need a way to use these actions to actually do the update. This can be done by using a pure function and this is rule #3.

Rule#3 — Changes are made with pure functions

Magic happens here. We need a simple pure function, which, as a parameter, takes the current state of the application and an action to perform on the state, and then returns the updated state. These functions are called reducers.

function booksReducer (state = [], action) {
// Magic is happening here...
  }

These are called reducers because they take the collection of values, reduce it to an updated state and then return it. Since reducers are pure functions they do not mutate the original state. Instead, they return the updated state in a new object. Our application can have one or more than one reducer. Each reducer can have a relevant state to perform specific tasks.

function booksReducer (state = [], action) {
    switch(action.type) {
        case ADD_BOOK_TO_THE_CART:
            return state.concat([action.bookId]);
        case REMOVE_BOOK_FROM_CART:
            return state.filter( book => book.bookId !== action.bookId);
        // a few more actions
        default:
            return state;
    } 
}

Since reducers are pure functions, they should have the following attributes:

  • Given the same input, it should return the same output every time — No mutation is allowed.
  • No side effects — No API call data change from an external source.

The process.

If we connect the dots, Redux is a library which has a store that contains a state tree and a few methods to interact with the state. The only way to update a state inside a store is to dispatch an action and define a reducer function to perform tasks based on the given actions. Once dispatched, the action goes inside the reducer functions which performs the tasks and return the updated state to the store. This is what Redux is all about.

State update flow in Redux

What have we learned so far?

Let’s summarize what we have learned so far to connect the dots.


  • Redux — An opensource predictable state container
  • State Tree — A plain JavaScript object which contains whole application state
  • Three ways to interact with a state (the only ways):
  • Store — A single unit which contains state tree & methods to interact with the state tree
  • Actions — Plan Javascript objects to describe the action taking place
  • Reducers — Pure Javascript functions to take current state and an action to return a new state

Since Redux is an independent library which can be used with React, Angular or any other library, I avoided making a sample application with any of these view libraries. Instead, I focused on the core Redux concepts only.

Redux can be overwhelming at first and if you are a newbie or junior developer it can give you a tough time. But consistency and a positive attitude is the key to success.

Originally published on https://medium.freecodecamp.org



Redux in React

Redux in React

React Redux is maintained by the Redux team, and kept up-to-date with the latest APIs from Redux and React.

React Redux is maintained by the Redux team, and kept up-to-date with the latest APIs from Redux and React.

React is all about moving parts that pass information to each other. You will notice sometimes you have really long chains that go through several containers and several components. This can be a hassle if the data got messed up in one of the steps and you have to slowly backtrack and look through each part to find the error. there is where Redux comes into play! Redux stores all of your state information in a separate object, and any component can get the information it needs from this object. So instead of going home => container1 => component1=> component2, it will go home => Redux Object => component2. Lets see how this all works!

First is the reducer function.

You have two objects that are separate from everything else, the state and the action. The state contains, well, the state of your page, and the action contains the instructions to update that state.

let state = {name: "abc"}
let action = {type: "JOE-IFY"}

To allow action to modify state, you need a function.

function changeState(state, action) {
   if (action.type === 'JOE-IFY') {
      return {name: 'Joe'}
   }
}

If the action type is ‘JOE-IFY’, change the state of name to be “Joe”. There can be many different commands to change names, typically a switch case it used. However, to make sure a null or undefined is never returned a default case is added that returns the previous state.

function changeState(state, action) {
   switch (action.type) {
      case 'JOE-IFY':
         return {name: 'Joe'}
      default: 
         return: state
   }
}

Now if you ran the changeState function with the state and “JOE-IFY” you would get {name: “Joe”}.

If you had another action type, for example to change the name to “Bob” it would look like:

function changeState(state, action) {
   switch (action.type) {
      case 'JOE-IFY':
         return {name: 'Joe'}
      case 'BOB-IFY':
         return {name: 'Bob'}
      default: 
         return: state
   }
}

Now if you instead ran it with the function “BOB-IFY” you would get {name: “Bob”}. This changeState function is called the “reducer”, as it reduces the state and action into a new state.

You can make it more complicated as well, since an action can have multiple attributes.

let state = {name: "abc"}
let action = {type: "CHANGE_NAME",
              newName: "Spooderman"}

You will have to change the function such that it changes the state of name to that of newName. Something like:

function changeState(state, action) {
   switch (action.type) {
      case 'CHANGE_NAME':
         return {name: action.newName}
      default: 
         return: state
   }
}

This is the gist of how a reducer function works.

Using Redux in a React App

First install redux.

npm install redux

Install react-redux.

npm install react-redux

Inside your “src” folder, create a “reducers” folder, and inside the “reducers” folder create a “reducerFunctionName.js” file.

Redux gives you the createStore() function, which when called returns the state. React-redux gives you the “provider” component, where store is passed in and is subsequently passed down everywhere else. React-redux also lets us re-render whenever the specified changes to the state happen via the connect method. Import them both into index.js. Also import your reducer function.

import {createStore} from 'redux';
import {Provider} from 'react-redux'
import reducerFunctionName from './reducers/reducerFunctionName.js'
const store = createStore(reducerFunctionName);
ReactDom.render(
   <Provider store={store}>
      {' '}
      <App />
   </Provider>, 
   document.getElementById('root')
)

Now we can pass the store and access it in every component. To any component that wishes to access the store, import connect from react-redux and modify the export.

import {connect} from 'react-redux'
const mapStateToProps = state => {
   return {
      name: state.name
   }
}
const mapDispatchToProps = state => {
   return {
      changeName: () => dispatch({type: "CHANGE_NAME"})
   }
}
export default connect(
   mapStateToProps,
   mapDispatchToProps
)(App);

mapDispatchToProps allows us to have access to the “changeName” function, which is what we are calling us passing in action.type “CHANGE_NAME” to the reducer. Similarly, name is provided by the mapStateToProps function, which gives us access to the name in the state.

Your components now have access to the state information inside the store object, and are able to access the functions needed to change the state. Just about done!

One final thing. Now what if you had multiple functions? You can theoretically transform all of them into different cases for the same reducer function, but this would be weird; you would have a case for “CHANGE_NAME”, a case for “BUY_FOOD”, and other cases for tons of weird things that have nothing to do with each other. It is better to separate out the reducer functions. This can be done through “combineReducers”.

In the “reducers” folder create a new file called “rootReducer.js”. At the top enter:

import {combineReducers} from 'redux'

Then copy paste your other reducer functions over, but without the export default part in front of them. Then add it to the end.

export default combinedReducers({
   nameChanger,
   colorChanger
})

Note that now to access information from on of the reducers you have to specify the reducer name first now, so instead of “state.name” if name is stored in the nameChanger function you need to do “state.nameChanger.name”.

Go back to your index.js and import rootReducer from “./reducers/rootReducer.js”, you don’t need the earlier individual file imports anymore.

Your finished combinedReducer should look something like this:

import {combineReducers} from 'redux'
function colorChanger(state = {color: "red"}, action) {
  switch (action.type) {
    case 'CHANGE_COLOR':
      console.log(state);
      return {color: action.newColor}
    default:
      return state;
  }
}
function nameChanger(state = {name: "zed"}, action) {
  switch (action.type) {
    case 'CHANGE_NAME':
      console.log(state);
      return {name: action.newName}
    default:
      return state;
  }
}
export default combineReducers({
  nameChanger,
  colorChanger
})

And an example app.js that uses the above reducers might look something like:

import './App.css';
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Something from './containers/Something.js'
class App extends Component {
handleChange = (event) => {
    this.props.changeName(event.target.value)
  }
handleChange2 = (event) => {
    this.props.changeColor(event.target.value)
  }
render () {
    return (
      <div className="App">
        <form>
          <label>
          NewName: <input type="text" onChange={event => {this.handleChange(event)}}/>
          <br/>
          NewColor: <input type="text" onChange={event => {this.handleChange2(event)}}/>
          </label>
          <br/>
          <input type="submit"/>
        </form>
        <p>{this.props.name}</p>
        <p>{this.props.color}</p>
      </div>
    )
  }
}
const mapStateToProps = state => {
  return {
    name: state.nameChanger.name,
    color: state.colorChanger.color
  };
}
const mapDispatchToProps = dispatch => {
  return {
    changeName: (event) => dispatch({type: 'CHANGE_NAME', newName: event }),
    changeColor: (event) => dispatch({type: 'CHANGE_COLOR', newColor: event })
  };
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

The default states for name and color are shown at the bottom. The redux state for name and color can be updated through the input bars, and the updated state is shown again with the new name and color.

And we are all done! That was a long ride and took me quite a while to figure out, so hopefully this guide helps you learn Redux faster than I did! Happy coding with your newfound knowledge of Redux!