Build Youtube in React 22: Prepare project to fetch data
Let’s recap, we successfully load
Youtube's client library, we set up some boilerplate code for the
Youtube endpoint and you know the basics of
redux-saga. However, before we finally start fetching data, we need to prepare and restructure our project a little bit. We will refactor it and think about the best way on how to organise our
1.1 Separation of concerns
Home component is the first thing users see when they load the page. Therefore, it makes sense that it is loading its content on its own by reaching out to the
If we now add our actions and connect to the
Redux state, we mix how our
Home feed looks with how we
fetch data. This is not really ideal from a software engineering perspective. Therefore, we will put the entire markup into a separate component called
HomeContent. So the data fetching logic will live inside
Home and the markup and design inside
- Create a new directory inside
Homeand call it
- Add a new file called
HomeContent.scssinto the directory you just created
Now the only thing we have to do is to move the content of
render method inside the
We also move the SCSS from
HomeContent.scss and rename the root
div's class from
1.2 HomeContent tests
Let’s add a quick snapshot tests so we can tell from our commits what we changed as we are building it out.
- Create a new directory inside
HomeContentand call it
- Add a new file called
HomeContent.unit.test.jsinside the directory you just created
If you run all our tests, you should see that we now have a snapshot for
2 Fetching Most Popular Videos
The first video grid in our
Home feed will contain the top
12 most popular videos.
The API endpoint we are about to hit is the Videos endpoint.
If you click on this link, you will see what parameters to use to fetch the most popular videos from
Youtube in the
2.1. Most popular videos response format
But wait, before we actually create all the logic, let’s think about how we will actually store videos.
In terms of
Video endpoint’s response looks like this.
For brevity, we excluded some properties otherwise the response gets too long. Please have a look at the endpoint’s response yourself by checking out the API explorer.
If you have a closer look at the endpoint’s response, you see that the video contains an
id field contains a unique identifier and is sort of the primary key if you are thinking in terms of relational databases.
2.2. Let’s talk about state
Here’s an example
Redux state of our current application. Currently we only save whether we successfully loaded the client library
Here’s how we will extend it:
As you can see, we added a new property called
videos as a top level field to our
Redux state. This is where everything related to video will live in. Since each video is uniquely identified by its
id, we nest the
byId object inside our
videos object. In here, we create some sort of “dictionary “ in which we associate each video with its
id as a key.
We also added a
mostPopular object inside
videos. It contains all the information we would like to store. First of all, we’re only storing the most popular videos’
ids in the items array. We put the actual content inside the
byId object. Now if you are more familiar with Redux, you immediately saw that this state is normalised. If you are not familiar with the concept of normalised states, you can read about it in the Redux documentation.
We also store the total amount of results as well as a next page token. If you fetch some entities from a
Youtube endpoint, the
API will only give you a few results. Otherwise it would take seconds to load and we probably only need a few resources anyway.
Youtube supports pagination for pretty much any endpoint. Suppose we have already loaded the top
5 trending videos on
Youtube. If we now want to load additional
5 videos, we can simply send our
nextPageToken along with our request. The endpoint will then return detailed information on video
10 and will also return us another next page token for a follow up request.
Youtube's boilerplate code will eliminate any fields in the payload where the value is
null, so if we fetch for the very first time and pass
nextPageToken, we won’t run into issues.
2.3. Alternative state designs
The purpose of these tutorials is not to just show you the code, but to explain why we do certain things in a certain way.
We could have stored the videos directly in an array. However in this case, we have problem if we are searching for a video with a particular
id. In the worst case, we would need to search through the entire array (
O (n)) to find one video. This is of course inefficient. In the state we have chosen, we have a constant lookup time (
videos.byId['someId'] is just a lookup in a hash table.
There’s a bunch of other issues with this state design, but these issues only occur once we store data from more endpoints in our state. We will talk about this later. For now, always aim at keeping your state normalised. This is really important!
2.4. Best practices for action type names in Redux
Before we create our first action that will reach out to the network, let’s agree on some conventions.
- If we fetch data from a remote server, we always distinguish three types of actions.
- When we want to reach out to an endpoint, the action gets the suffix
- if the request succeeds, we append the
SUCCESSsuffix to the original action, e.g.
- If the request fails, we append the
FAILUREsuffix to the original action type, e.g.
Having a consistent action type naming makes our code more readable and easier to understand. This is good, especially when our app gets bigger. Since we now know what kind of suffixes we will have, let’s create a method to generate them. We don’t want to type them out manually all the time.
Head over to your
src/actions/index.js file and add the following code:
3 Wrap Up
All right, we now have everything we need to create our actions.
I know this is kind of a lengthy process, but real world apps are indeed more complex than life-changing weather apps.
The conventions and methods we introduced in this tutorial are not specific to our
Youtube application. You can use them in any
React / Redux project in the future.
You can find all the code in our Github repository.Follow @productioncoder
Please follow me on Twitter @productioncoder to stay up-to-date. I’m happy to receive feedback of any kind.
If you are interested in more high-quality production-ready content, please enter your email below.