Build Youtube in React 24: Create reducer for most popular videos
We already created the
sagas for the most popular video endpoint.
However, we still lack a reducer that handles the
2 Video reducer
2.1 Creating the video reducer
Since our video data will live in its own
sub reducer, let’s create a new file for it.
- Create a new file called
videos.jsand put it inside
First, we set up the basic structure of our
reducer's initial state consists of the
mostPopular object which are both empty. That makes sense right? Because at the beginning, we haven’t yet fetched any information.
Currently, we’re only handling the case when our
MOST_POPULAR_SUCCESS case, i.e. if we successfully receive the data.
To not clutter our reducer, we put all the logic inside an own method called
Before you read the code, please have a look again at the JSON response the server returns so it’s clear what this function is doing.
At first, we create an object called
videoMap is some sort of dictionary where we associate each video with its
id. This video map will be merged into our
byId object later on.
And here comes the interesting part. If we send along a
nextPageToken, the server’s response will contain a
prevToken property. So by checking whether
prevToken is there, we know whether we already fetched some videos from this endpoint or not. If
prevToken is not there, then we haven’t stored anything from the endpoint yet.
If we do have a
prevPage token, we don’t want to throw away the videos we already fetched. In this case, we’re just appending the new videos to the videos we already have inside
Finally, we update the
mostPopularVideos object by storing the total amount of videos we could fetch (
next page token and the
items is an array that contains video
ids. The actual video details are all stored inside the
byId object in our global state.
Like so, we have all the video details at one place.
2.2. Combining reducers
Now, we only have to plug in our videos reducer into our
Head over to the
src/store/reducers/index.js file and add it to our
This essentially says: our global
reducer is composed of several
sub reducers. Each sub reducer is responsible for one particular part of the state. The
api reducer will be responsible for the
api object inside our global state. The
videosReducer will handle everything that will go inside
sub reducers don’t know each other and they also don’t need to. If you frequently think about accessing another part of the state from a
sub reducer then you should think about refactoring your state altogether. We want a clear separation of concerns that leads to low coupling.
Otherwise it is pretty hard to maintain it.
2.3. Using our fetching logic
Now that we have all the logic in place, we just have to use it. Our
Home component will display the most popular videos, so let’s go ahead and fetch some data.
What did we do? Well first of all, we created two new functions:
mapStateToProps function is used to get the api.
libraryLoaded field from our global state. We use the selector
getYoutubeLibraryLoaded for this. The
mapDispatchToProps function allows our component to start the fetching process of the most popular videos by dispatching an action. Note that we use
Redux' connect helper in the
export default statement.
Also note that we make use of two lifecycle methods. The first one is
componentDidMount runs once our component gets plugged into the
DOM. This lifecycle method is typically used for reaching out to the network.
In case we already loaded the
Youtube library, we immediately start fetching the most popular videos. However, there’s one important detail to note. Remember that we have to pull in the
Youtube library from a
CDN asynchronously. So oftentimes if
componentDidMount is called, we haven’t yet loaded the
Youtube library. Without the library, we cannot reach out to the
Youtube API. This is why we rely on
Youtube library is finally loaded,
componentDidUpdate gets called because we sort of “subscribed” to the
libraryLoaded property from our global state via the
youtubeLibraryLoaded selector. In
componentDidUpdate, we check whether it was
getYoutubeLibraryLoaded that was updated and not something else. If this is the case, we start fetching the most popular videos.
Well if the library is not loaded when the component is mounted, why do we use
componentDidMount anyway? Remember that we will have different pages in our app. So a user might navigate back from another component (e.g.
Watch) to our
Home feed. In this case, we already loaded the
Youtube library and therefore we can make the request immediately.
2.4. Testing our Youtube most popular videos fetching workflow
Remember that one tutorial where we added support for the
Now we will make use of it to verify that our magic works.
Start your app and click the
Redux Devtools icon.
When you start the app, you should see something like this.
Click on the image to see it in high resolution.
3 Wrap Up
Yeah, it actually worked. We’re successfully fetching the most popular videos from the
Youtube endpoint and store it in our
Right now, our app still looks a little bit boring because haven’t populated our components with the data yet.
Thanks for taking the time to read this tutorial. You’re a real fan.
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.