Using Entity Adapters

In this lesson, we're going to use Redux toolkit Entity Adapters

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the The newline Guide to Fullstack ASP.NET Core and React course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to The newline Guide to Fullstack ASP.NET Core and React with a single-time purchase.

Thumbnail for the \newline course The newline Guide to Fullstack ASP.NET Core and React
  • [00:00 - 00:17] In this lecture, we will discuss about efficiently getting our courses from the API. Generally, what happens is you visit the home page, you make an API call to get the courses, then you visit some other page, come back to the home page again and make the same request all over again.

    [00:18 - 00:42] There is a solution though, let's visit our usage guide. And here, if we look at normalizing data with Create Entity Adapter, it says Redux Toolkits Create Entity Adapter API provides a standardized way to store your data in a slice by taking a collection and putting it into the shape of ID and entities.

    [00:43 - 00:54] Along with this predefined state shape, it generates a state of reducer functions and selectors that know how to work with the data. This basically knows how to do some basic operations on your data.

    [00:55 - 01:06] You obviously cannot replace it with your server, but you can use your frequently used data in a slice. And rather than calling the database, ask your state to provide this data.

    [01:07 - 01:11] This sorts your data with the keys and help you query it efficiently. So what can we expect?

    [01:12 - 01:21] We will make an API request the very first time the home page loads. We will take the data, store it in our state, which will normalize it.

    [01:22 - 01:35] It will then take the ID from our course and make it a key of the normalized data, with value being our individual course. After that, if you want to go to our detail page, we don't need to make an API request.

    [01:36 - 01:42] Rather, we can check with Redux if that particular course ID is a part of the store data. If it has, we can query it.

    [01:43 - 01:52] So obviously, no need to go to the database again and again, which will make our requests so much faster. Now let's start implementing it.

    [01:53 - 02:09] Let me close it and inside Redux folder and inside slice, let's create a new slice and we will call it course slice. First of all, we will use the create entity adapter and store it in a variable.

    [02:10 - 02:24] We will call it courses adapter. Here we will use create entity adapter, which is provided by Redux toolkit.

    [02:25 - 02:39] We also need to give it a type and since we are storing a courses, let's give it a type course and it will be imported from models. And we don't have to pluralize it because it has built in functions that will take care of it.

    [02:40 - 03:06] Now we will use the create async thunk method to make a call to our API and below this, I will create a new variable and we'll call it get courses async and after this , I will use create async thunk again. We are going to call our courses list method, which returns paginated course.

    [03:07 - 03:17] So the result can either be paginated course or can be undefined. We are not passing any parameter right now.

    [03:18 - 03:25] So we can put the second argument to be void. Now we can use our type prefix here.

    [03:26 - 03:38] Let me bring it down and here I can write course slash get courses async. Now let's make an async call.

    [03:39 - 03:44] So we will use async. We don't have any arguments to pass for now.

    [03:45 - 04:18] So we will not use it and inside async, we will use our try catch block, try and then catch, which will have access to the error object and we will simply log the error for now and inside our try block, let's return await agent dot courses dot list. We can now create our cost slice and we are going to create it like before.

    [04:19 - 04:37] So below we can use export const course slice and again, this will be equal to create slice, which we have seen before. And like before, we will give it a name, which will be simply course.

    [04:38 - 04:50] We also need the initial state. So let me write initial state, but this time we will be using our courses adapter dot get initial state.

    [04:51 - 05:21] So let me down courses adapter dot get initial state inside our get initial state from courses adapter, we can also use some additional states. So we can use a state called courses loaded courses loaded and keep it false in the beginning and also the status of the call status, which will be idle.

    [05:22 - 05:38] We can make our courses loaded to be true once we make our first request to the API. After this, we can write our reducers, which we haven't created for now, but let's write reducers and pass an empty object and this will resolve all the errors.

    [05:39 - 05:56] If you remember when we are using async thunk, we can use extra reducers, which gives us access to the builder. So let me write extra reducers and we will have access to the builder.

    [05:57 - 06:07] So inside we can write our first add case. So I will use builder dot add case and we will have the condition for pending.

    [06:08 - 06:33] So I will write get courses async dot pending and we will use state to change the status to be pending when the request is pending. Let's write another add case for the get courses async dot fulfilled.

    [06:34 - 06:48] So let me copy it to avoid writing the same thing again. And here I can replace pending with fulfilled and with state, I will also use the action.

    [06:49 - 06:55] Here we don't need the status to be pending. So I can make it idle and on top.

    [06:56 - 07:03] We will use our courses adapter. So we are using the courses adapter to store the array of courses, which will normalize it.

    [07:04 - 07:15] It gives us access to so many credit operations, like any other object relational mapper. So let me write courses adapter.

    [07:16 - 07:22] And if I write dot, you see, there are so many credit operations we can take advantage of. For our use case, we will use set many.

    [07:23 - 07:33] We will use state as the first argument here. And the second argument will be the payload, which in our case is action dot payload dot data.

    [07:34 - 07:43] And let's replace question mark with an exclamation. We are using data because action not payload gives us access to the paginated course, which has a page index and the page size.

    [07:44 - 07:50] But to get access of the courses, we need to access the data. Finally, we can create a case for the rejected state.

    [07:51 - 08:06] Let me copy it again from top. And here I will change pending to be rejected and changes status from pending to idle.

    [08:07 - 08:15] Now we have a new slice. So we need to go to the configure store and add it inside our reducers.

    [08:16 - 08:26] And here I will write course. And here I can write course slice dot reducer to see what it does.

    [08:27 - 08:37] We can install Redux step tools, which is a perfect tool to represent what Redux is doing and changes its making to the state. Let's install and look at it next.