02Geek HTML5 and JavaScript, TypeScript, React, Flash, ActionScript online School
Previous VideoNext Video

Creating a Reducer for the Checkboard

Creating a Reducer for the Checkboard

In this tutorial, we will explore how to create a reducer for a checkboard in a Redux application. We will learn how to use multiple reducers and combine them using the combineReducers function. By the end of this tutorial, you'll be able to create a more dynamic and structured reducer that can be easily integrated into your application.

Introduction

A reducer is a crucial component in Redux that defines how the application's state changes in response to actions. In this tutorial, we will focus on creating a new reducer for a checkboard, which will allow us to build a dynamic board structure. We will also discuss how to manage multiple reducers effectively in a single store.

Step-by-Step Implementation

1. Creating a New Reducer

The first step is to create a new reducer for our checkboard. This reducer will define the initial state and handle the actions related to the checkboard.

const initialState = {
  color1: "black",
  color2: "white",
};

const boardReducer = (state = initialState, action) => {
  switch (action.type) {
    default:
      return state;
  }
};

Here, we define an initial state for the board, which includes two colors (color1 and color2). The reducer currently handles no specific actions, so it simply returns the state by default.

2. Combining Reducers

Redux recommends having a single store for the entire application. However, as your application grows, managing everything in a single reducer becomes cumbersome. To address this, Redux provides the combineReducers function, which allows you to split the state management into multiple reducers while keeping a single store.

To combine our boardReducer with other reducers, we use combineReducers as shown below:

import { combineReducers, createStore } from 'redux';
import counterReducer from './counterReducer';

const rootReducer = combineReducers({
  board: boardReducer,
  counters: counterReducer,
});

const store = createStore(rootReducer);

In this example, we combine the boardReducer and a counterReducer into a rootReducer. The rootReducer is then used to create the Redux store.

3. Understanding Combined Reducers

The combineReducers function accepts an object where each key represents a slice of the state, and the corresponding value is the reducer responsible for managing that slice. In our example, board and counters are two slices managed by boardReducer and counterReducer, respectively.

This means that the store will now have the following structure:

{
  board: {
    color1: "black",
    color2: "white",
  },
  counters: [/* counter state here */]
}

When an action is dispatched, every reducer receives that action. However, only the reducer that is designed to handle the action will update its part of the state. In our example, if the ADD_COUNTER action is dispatched, the counterReducer will handle it, while boardReducer will simply return the current state without any changes.

4. Adding More Functionality

In the next steps, we can add more functionality to our boardReducer. For example, we could add actions that change the colors of the board dynamically.

const boardReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'CHANGE_COLOR':
      return {
        ...state,
        [action.payload.colorKey]: action.payload.colorValue,
      };
    default:
      return state;
  }
};

In this example, we add a CHANGE_COLOR action that allows us to dynamically change the color of the board squares. The action payload contains the key (color1 or color2) and the new color value.

5. Testing the Implementation

After creating the reducer and combining it, it's essential to test it within your application. Make sure to dispatch actions and verify that the state updates correctly.

store.dispatch({
  type: 'CHANGE_COLOR',
  payload: {
    colorKey: 'color1',
    colorValue: 'red',
  },
});

console.log(store.getState().board.color1); // Output: 'red'

Conclusion

In this tutorial, we:

  • Created a reducer for the checkboard.
  • Learned how to combine multiple reducers using combineReducers.
  • Discussed how the combined reducers interact within a single Redux store.

These concepts are fundamental for managing a complex application's state effectively. By combining reducers, we can keep our code modular and easy to maintain. In the next steps, you can further enhance the board reducer by adding more actions to make it even more dynamic.

Video Transcript

00:00In this lecture, we're gonna create a reducer
00:02for our checkboard.
00:04And with that, see
00:05how do you integrate multiple reduces reducers using the
00:09combined reducer function.
00:11Alright, let's make our application a tad,
00:14a smidge bit more realistic.
00:16So to do that, what I want to do is I want to create a board
00:19that will be derived out of these numbers
00:22that we're growing here.
00:23So basically, if it's a one by one, we'll have a one by one,
00:26kind of like checkmate type style of board.
00:29So let's go ahead and create this structure.
00:32Now, to do that, I'm gonna do a few things in the process.
00:34And I wanna start off from that.
00:37The idea that I really want to have here, a mechanism
00:40that would describe the color of our squares, maybe Otto,
00:44a mechanism that would describe the width, the height.
00:47But we're not gonna go that deep into it.
00:49But what we're gonna do is we're gonna have a
00:51mechanism for our board.
00:52Another a dynamic element here.
00:55It's gonna be something in our store itself.
00:57I wanna have another store and I'm gonna go ahead
01:00and create it or another, uh, reducer you could say.
01:03And I'm gonna go ahead and create it.
01:05And what I'm gonna do is I'm gonna create a new board.
01:08Now for our board itself, what I really want to do is I want
01:10to have a state, and I want that state
01:12to have a default value.
01:14But this time around I want that default value.
01:17And I'm just building in here the structure
01:18of any, any reducer.
01:20And you can have multiple reducers.
01:23In this case, what I want to have is I wanna have a state,
01:25and I want that state to have a default value
01:27of let's say color one is black
01:31and color two is gonna be white.
01:35I should really stick to the same quotation marks.
01:39You know, it's something I do often
01:40and I know people always give me feedback on that.
01:43So I'm gonna fix that. I'll just do always double quotes.
01:47Okay? So we have here our core state
01:50and what I wanna do with our board, it's not gonna do,
01:51literally not gonna do anything for now.
01:54Uh, but I'm gonna use a switch anyways
01:56and have your type just like we've had previously.
01:59Now as we go through this, and I'm just gonna go ahead
02:03and have your just a default, literally anything that comes
02:06through right now is just gonna return our state.
02:08Now, technically speaking in reduce,
02:12we do not create separate stores.
02:14We always have only one store.
02:16And our store itself should be a co a combination
02:19of all the different reducers that we have.
02:22Now, the way we do that is we call in from our create store.
02:26Lemme just go ahead and do that.
02:27In our create, instead of only creating a store,
02:29we're also gonna, uh, call the combined reducers.
02:33And the combined reducers is literally a method
02:36that accepts a list of, well, it, it accepts an object
02:40that contains all the reducers
02:42or all the top level reducers.
02:44'cause you could have smaller reducers
02:45that are called from within as well.
02:47If he choose to do so.
02:49By the way, every single reducer is gonna get
02:52every single action.
02:53And thus, if we have here, for example, an action
02:56of add counter, our board
02:59Is gonna be called as well.
03:00But because it doesn't have an ad counter,
03:02it means it does not have anything to do with it.
03:05And thus it will return the state
03:06as it was without changing it.
03:08Now the job of our combined reducer itself,
03:12and lemme just go ahead and create it so we have your close.
03:17Close, okay? 'cause we're calling our method twice.
03:20So we, besides our counters, we also want
03:22to add now a board.
03:24Now our board encounters are literally, it's gonna cycle
03:27through them and call each one of them sending
03:29to them only the chunk that is related to them,
03:31which also means by the way,
03:33that now we don't have a counter as an array anymore
03:36as our base data type.
03:39But instead of that, when we call our store,
03:41so if we go back into our store itself, any place
03:44where we get our store, this will not be equal anymore
03:47because we would need to append to it our counter.
03:50So literally any place here
03:52that we're actually approaching our get state,
03:54we wanna also go into our, for now,
03:59I'm just gonna go ahead into our counter itself,
04:01and we're gonna make some modifications
04:02to this very, very shortly.
04:04But I'm, I'm just gonna go ahead here and define those.
04:08So literally what I'm doing here is IB,
04:10once I've created our store itself,
04:13and let me just check that we don't have your
04:15any surprise errors.
04:16Uh, so surprise errors we have your small fail
04:20type is not defined.
04:21And that is true because we didn't extract out
04:24of the action anything it was.
04:25So we need to set it to be action type. Okay?
04:28So that's good. And we have your, uh,
04:31render without crashing, which is fine
04:33because that's in our application itself.
04:35And currently our application itself is actually not
04:38fetching the right data, right?
04:39Because right now it's going
04:41to the full data object when in reality it
04:44should be running through them.
04:45It should be running through our data do counters
04:49and it should map through that.
04:51Now I think that should cover it.
04:53But oh, and also here counters.
04:58And let's see if we have still errors. We sure do.
05:02So let's see, we have your one, uh,
05:03in our app itself, we have issues.
05:06Do we, do we do we, let's see, let's array to undefined.
05:10Okay, beautiful. Okay, so first of all,
05:11we're getting the value
05:12that was returned is not the value we expect inside
05:15of our test, but let's see, for which one it is.
05:18So let's see, let's see, let's see.
05:20So two different types of values.
05:22And that is when we are comparing two different values,
05:25where is the description?
05:26Step down from one to zero.
05:28All right, let's from zero to one as well
05:31and starting up with three counters.
05:33Okay, so starting up with three counters.
05:37Uh, it's not counter, it's counters.
05:40You see that it's sometimes these stuff are a little bit
05:42hard to find, but you know, these, these debugging tests are
05:46so, so powerful that it makes it so much easier.
05:48So there we go. We passed all the tests.
05:50Don't worry too much about our application
05:52if it still works or not.
05:53'cause I wanna stick to this board area and test that out
05:56As well. So
05:57first of all, I'm just gonna go ahead here
05:59and what I'm gonna do, and we're gonna do
06:01that in the next lecture 'cause let's just like
06:03recap what we just did.
06:05Although it's a small task,
06:06but it's a big one, it's a doozy.
06:08So literally what we did,
06:09and if we're ready, we're doing this,
06:10let's just double check that our, um, counter is working.
06:14We could add multiple counters.
06:16Everything is still working as it should have worked before.
06:19Now what we've done in this step is we
06:21created a new reducer.
06:23As we created that new reducer, we gave it a default value
06:27that is an object and currently it doesn't have any actions.
06:30Thus it returned to us, our state as it is Now,
06:34technically speaking, obviously we're gonna wanna change it,
06:37which we're gonna do that in the next lecture
06:39as we test it out.
06:40But once we've created another board, we combined all
06:43of our reducers into one mega reducer.
06:46By combining all those into one mega reducer,
06:49we b basically created a reducer of reducers,
06:53which will basically run through and send, uh, any action.
06:57It will, it will basically trigger the counters
07:00and trigger the board as well.
07:02If we have your step up, you, it will be called.
07:05But because no change has happened,
07:06our default is gonna return the default state
07:09or whatever current value the state is
07:12because that is the job of the create story.
07:14It will basically parse out through the combined reducers,
07:18parse out and send the relevant data
07:20into the counter itself.
07:21So when we're in the counter,
07:23we're only in a raise 'cause that's all we care about.
07:25When we're in our board, we're only in that specific items
07:27that relate to the board itself.
07:30Now, in the next lecture, what we're going
07:32to do is we're gonna go ahead
07:33and actually implement here a case
07:36and, uh, to listen to an action, to listen to
07:39and implement a change to our object.
07:41In our case, we're gonna wanna change our colors
07:43and that's what we're gonna do in the next lecture
07:46and then test it out.
07:50In this section, in this lecture, we saw how
07:52to use the combined Reducer function
07:54to combine multiple reducers.
07:56In the next lecture, we're gonna continue down the line
07:58of making sure that our changes that we're making inside
08:01of our new reducer is not actually overriding the state,
08:05but actually creating a new state object.
08:08And we're gonna see that in the next lecture. I.

Ready to Level Up Your Skills?

Join thousands of learners on 02GEEK and start your journey to becoming a coding expert today!

Enroll Now for Free!