Build Youtube in React 32: dynamic watch component
1 Overview
We’re done with our Home feed
, but we still need to make our Watch
component dynamic. In this tutorial, we will start fetching the data we need for it.
2 Making our video viewing component dynamic
2.1. Adding links to video thumbnails
We can scroll through our Home feed
, but when we click a video thumbnail nothing happens. We want the user to be redirected to our Watch
component.
This can be accomplished by using the react-router Link
component.
Let’s wrap the entire content inside VideoPreview
(src/components/VideoPreview/VideoPreview.js
) inside a Link
component.
Our VideoPreview
component now expects two new props
: pathname
and search
. The pathname
prop
is the absolute path to which the user should be redirected to. For example, if we want to get redirected to /foo/bar
, then pathname
must be set to ‘/foo/bar'
.
The search
prop is the query string that we want to append to the address, so if we want to add ?id=1234
as query parameters to our URL
, we need to set the search
prop to '?id=1234'
.
2.2. Updating video grids
Our VideoGrid
component inside src/components/VideoGrid
is responsible for creating video preview elements. Therefore, we need the component to pass a pathname
and a search
prop to VideoPreview
.
2.3. Verifying that the links in Home feed work
Go to the Home feed
, click on one video aaaaaand 😡
Nothing happens. Now why is that? Well the reason is Redux
.
When we included Redux, we also gave it control over when our component re renders. The issue we ran into is called update blocking.You can read more about it in the official react-router repository.
Basically, Redux
is taking control of our component and does not re render it when the URL
changes. A component is re rendered when at least one of its properties changes. So if we make the URL / location
a property of our App component then our component should be re rendered as soon as the URL
is updated.
The only thing we need to do is to wrap our App
component inside the withRouter
higher order component. The withRouter
helper basically inserts the current URL
as a prop inside our component. It is accessible via this.props.location
. So if our URL
changes, our App
component re renders and we get redirected.
Change the default export in your App.js
file like so.
Once you click a video thumbnail, you should now be redirected to /watch?v=...
This is not something I came up with, but this is how Youtube's URL
structure works
2.4. Intermediary Result
Click on the image to see it in high resolution.

It’s looking a little bit empty around here because we only have placeholders in here. We need to change that. But first, let’s think about what we need to do.
We need to display the video’s metadata (likes, dislikes) along with its title in here. Note that we will also need the text that goes into the video description. When we loaded information on trending videos in the Home feed
, we did not load the video description because it was not needed. Loading the video description for multiple videos also comes with quite a high latency. Therefore, it makes sense to load the description / the info box text
only when the user actually watches the video.
2.5. Scrolling to the top with react-router
Now you might have noticed an issue here. If scroll down the Home feed
and then click the video thumbnail, you end up in the Watch
component.
However, you might not have ended up at the top of the page. That is because we just go to another page, but keep our scroll position.
We don’t want to have such a behaviour. When the user navigates to another page, he/she should always end up at the top of the page.
Fortunately, this is a rather small issue that can be fixed pretty quickly. We will just create a component that always scrolls to the top when the URL
changes.
- Create a new directory inside
src/components
and call itScrollToTop
- Add a
ScrollToTop.js
file inside the directory you just created.
In our componentDidUpdate
lifecycle method, we check if the location has changed. If yes, then we use the window.scrollTo
function to scroll to the very top of the page.
In terms of rendering, the ScrollToTop
component will just return all its children. We use the withRouter
helper so that we have access to the current location.
Remember the AppLayout
component? In here, we make sure that we always have a top bar in our app. We can just wrap all that in the ScrollToTop
component and we’re good.
So head over to your src/components/AppLayout/AppLayout.js
file:
2.6. Extracting search parameters from URL in React
Ok, back to the topic and back to the Watch
component. Once we end up inside our Watch
component, we will reach out to Youtube’s videos endpoint and fetch information on a particular video. Remember that we are adding the video id
to the query string of our URL
. So if our URL is /watch?v=abcdef
, then we need to fetch detailed information on the video with the id abcdef.
Let’s add a new function inside our Watch
component that extracts the video id.
Pretty easy isn’t it 🤓
2.7. Fetching video details from Youtube endpoint
Before we start creating our action creators, we first need to understand to which endpoint we want to reach out.
The goal is to load very detailed information on a video. Wee need the video title, the amount of likes / dislikes and its description.
It turns out that we need to reach out to the Videos endpoint again which we used to fetch trending videos.
However, this time around, we just want to fetch information on one particular video identified by a video id
.
Please have a look at the API explorer to see what I mean.
Here’s an example request to get more information for the video identified by id Ks-_Mh1QhMc
That’s an easy one. Head over to the src/store/api/youtube-api
file and add the following code:
Note that we are making use of the fields
parameter to not load too much information. Like so, we get a faster response.
2.8. Fetch watch details action creator
To fetch more detailed information on a video associated with a particular id, we need to create actions first.
We will call this action WATCH_DETAILS
.
- Create a new file inside
src/store/actions
and call itwatch.js
We make use of our action creator methods to speed things up a little bit.
2.9. Video details watcher saga
To reach out to the endpoint, we need to create a watcher saga that forks a worker saga
when it detects the WATCH_DETAILS
event.
Let’s create a new file to not clutter our code
- Create a new file inside
src/store/sagas
and call itwatch.js
We start out with the easy part and create the watcher saga
first.
We listen to the WATCH_DETAILS_REQUEST
action type and extract the videoId
parameter from it. After that we fork
a worker saga
and pass along the video id
.
2.10. Video details worker saga
One hint upfront: we need to reach out to multiple endpoints to fetch all the information we need in our Watch
component. This means that we will need to make multiple requests concurrently and chain them together later on. We will do this step by step and start with fetching detailed information on a particular video.
Right now, we’re just firing one request. Therefore the approach with the requests array seems overkill. We will improve the worker saga incrementally and add more requests to it later on.
We use the all
effect whose semantics is comparable to Promise.all
) to perform all requests in the requests array. Once we are done, we dispatch the WATCH_DETAILS_SUCCESS
action. In case the request is not successful, we dispatch the WATCH_DETAILS_FAILURE
action.
2.11. Wiring up watch details watcher saga to root saga
To actually make use of our logic, we need to include our watcher saga
into the root saga
.
Head over to your src/store/sagas/index.js
file and plug our new watcher saga
in.
3 Wrap Up
We’re getting there.
In the next tutorial, we will work on the reducer
and will gradually fetch more data from the Youtube
endpoint.
Thanks for reading, you can find the project’s 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