Build Youtube in React 33: reducer for watch video component
1 Overview
Let’s continue where we left off and start with creating the reducer
for our WATCH_DETAILS
action.
2 Adding watch details reducer
2.1. Let’s talk about state
It is important to understand where we store the more detailed information on the video we are about to fetch. It has to live somewhere in our global Redux
store.
When we have more information on a video, we will just add / update an entry in our videos.byId
“dictionary”. So the new state might look like this:
Have a look at line 10
. We simple replace or update the video associated with a particular id
. Now we also have the description for the video associated with id FLqvTE1Eqfg
.
Now that we are clear on how to store the data, we also know that we must update our videos reducer
.
2.2. Endpoint response format
Let’s first talk about how the endpoint’s answer is structured. Since we are using the all
effect, we expect to get an array of responses back. Right now we only perform one request, so we expect the array to only contain one element.
A typical response for the call we are about to make looks like this.
Remember that when doing a request with redux saga
, we also get a bunch of other stuff in our response we don’t really need. Generally, a response consists of three parts.
The result contains the response in the form of a JSON
object. This is what we will be working with. The entire response string is stored inside body
. We also get information on the response headers
.
Now we don’t care about the headers
and the body
for now and will just be working with the result
.
I’m just bringing this up so that the reducer
is easier to understand.
2.3. Reacting to watch details action in video reducer
We add a new case statement
to our switch
and now react to the WATCH_DETAILS_SUCCESS
action.
Let’s have a look at the reduceWatchDetails
function which does the actual work. We will first look at a quick and dirty solution and then do it properly.
We know that the items
array in the responses array will contain the details about a particular video.
So we could simply get the first element in the responses array. That’s the response we’re looking for. We also know that the items
array of the response (as shown above) will just contain one element because the video id
is unique. So we could simply take the first element in the items array and insert that into our videos.byId object.
This sort of works, but that’s not the quality we’re striving for. This parsing mechanism is very fragile. If we change the action later on and the first response is no longer the response with the video
details, our entire reducer
crashes and burns.
So let’s do this properly.
2.4. Robust watch details reducer
Instead of just taking the first response and hard-code an index, we just use the Array.prototype.find function.
The find function will return the first item that matches the condition we specify. We are searching for a response of kind youtube#videoListResponse.
Fortunately Youtube
returns the kind for each response it sends back. Once we have found the right response, we just pick the first video in the items
array. We know that this response will exactly contain one element because we explicitly ask for a video with a specific id.
Now you might argue, well what happens when I pass an id
which is actually not a video id
. Well, in this case, the promise gets rejected and we dispatch a WATCH_DETAILS_FAILURE
action instead of a WATCH_DETAILS_SUCCESS
action. So we basically don’t end up in the reduceWatchDetails
function.
2.5. Youtube video response types
Well, there is actually one more thing we could do. We have a hard coded string
in our find
expression. This is not best-practise. Therefore let’s create a file where we define the different kind of responses we are working with. Like so we are more flexible.
- Create a new file called
youtube-response-types.js
insidesrc/store/api
.
Add the following code:
Now we can update our find
function
call.
3 Fetching video details in Watch component
3.1. Wiring up watch component to action creators
Let’s test out our new reducer. For this, we need to dispatch the WATCH_DETAILS_REQUEST
action inside Watch
. Let’s first pull the dependencies from our global Redux
state in by using selectors
.
First of all, we pull the youtubeLibraryLoaded
from our Redux
state in. If the library hasn’t loaded yet, we cannot perform any requests.
We also pull in the watchDetails
action into our local state by using the mapDispatchToProps
function.
Finally we export our new component with the react-redux connect helper. Note that we are are also making use of the withRouter
helper because Redux and React router sometimes get in their way. We already covered this in the previous tutorial.
Let’s add the needed code inside the component itself.
The fetchWatchContent
function extracts the video id
from the current URL
. After that it starts the fetching process by calling fetchWatchDetails
.
We make use of our data fetching logic in componentDidMount
and componentDidUpdate
. Note that we only attempt to fetch data when the we already loaded the Youtube client library
.
3.2. Updating App component
Remember that we are now using a default export
inside our Watch
component. Therefore, we need to update the import
statement in our App
component.
4 Wrap Up
Go to the Home feed
and click one video thumbnail. After that you should be redirected to /watch?v=...
Let’s check out our store with the Redux Dev tools
extension.
Click on the image to see it in high resolution.

Nice, the video details are fetched and stored in our Redux store.
In the next tutorial, we will start making use of this data and actually show it in the UI
.
You can find the entire code on Github.
Follow @productioncoderPlease 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.
Recent Comments