Build Youtube in React 15: Video Metadata
1 Overview
In the last section we started working on the layout of our Watch
component. So far, we have static versions of the Video
and the RelatedVideos
component.
We still need a component that displays the video’s metadata such as views and the channel name.
Let’s see what we’re up to. Click on the image to see it in high resolution.

Notice the information about the video at the bottom of the screenshot.
Click on the image to make it bigger. Otherwise it might be hard to see.

2 Video Metadata component
2.1. Create the files
Our new component will not reach out to some web service or API
later on. It’s just responsible for laying out some information as shown above. Therefore, we consider it a presentational component and put it into src/components
.
- Create a new directory inside
src/components
and call itVideoMetadata
- Add a
VideoMetadata.js
and aVideoMetadata.scss
file inside of the directory you just created.
2.2. Wiring up video metadata with Watch
To actually see what we are building out, let’s quickly add VideoMetadata
as a child to our Watch
component.
We can now also remove the coloured div
that was supposed to schematically represent the video metadata component.
Note that we also added VideoMetadata's
skeleton so that our code editor is not showing an error. We also added the viewCount
prop which is supposed to be the total amount of views a video got so far.
Right now, it doesn’t do anything. But I just added it here because it doesn’t do any harm and we’ll soon see how we actually use it.
2.2. Design VideoMetadata component
It’s time to fill the component with life.
We expect to get the total number of videos via a prop called viewCount
. Since we might also get a String
, we convert it into a number and call toLocaleString
. This method formats the number depending on where you are located. For example, in the US
, we use a comma to as a delimiter for 3
digits because it’s better to read. In other countries this is not the case. Fortunately, we don’t have to wrestle with these issues because Javascript
will format the number accordingly.
Our parent container is a div
with the class .video-metadata
. We use it to add a little bit of cosmetics by adjusting our component’s font size and the font color. The first element is a simple h3
heading.
We’re done with the heading and can place our video statistics right underneath our heading. The video view count should be placed on the left. On the right we would like to have some buttons and more information. We’ll make use of flexbox
and create a flex
container div
with the class .video-stats
. For illustration purposes, please have a look at this image. Click on the image to see it in high resolution.

The rectangle with the blue background is supposed to be our our .video-stats
container. Our .video-stats
container will have direct children. The first one will be the view count span
which is shown in orange. The second child will be a div
that holds the rating and a few buttons. We still need to build out the components shown in red.
By setting justify-content: space-between
, we instruct our flex-container to maximize the space between its children. Since it will only hold two direct children, the children will be floated to the left and right respectively. Because we want the children to be aligned vertically, we set align-items: center
.
2.3. Introducing the Rating component
If you have a thorough look at the red rectangle in the image above, you see that we need some sort of Rating
component. This Rating
component displays the amount of likes and dislikes and shows visually the percentage of likes in a tiny progress bar. Let’s have a closer look. Click on the image to see it in high resolution.

Well, if we use a little bit of color, it kinda looks like a 2×2 grid, right?

Note that the progress bar will span two cells at the bottom of the grid.
- Create a new directory inside
src/components
and call itRating
- Add a
Rating.js
and aRating.scss
file inside of the directory you just created.
2.4. Building the Rating component
Let’s think about its props
first before we create the markup. This component needs the number of likes
and dislikes
as props
so it can adjust the progress bar.
Here’s the component’s skeleton:
We can only show the progress bar if we know the amount of likes and dislikes. Therefore, we first check if these values were passed via props. If yes, we create a Semantic UI Progress component,
2.5. Rating layout
Now we can take care of the component’s markup Our Rating
component’s layout is based on a 2x2
grid.

Our root element is a div
with the class .rating
. We make it it an inline grid container
by setting the display: inline-grid
property. By using inline-grid
instead of grid
we force our grid
container to become an inline
instead of a block
element. This makes it easier to position the Rating
component directly next to other components without adding additional SCSS
.
Our grid
container has two rows and two columns. Have a look at our grid
property. We instruct our grid
container to size our two rows automatically. So far so good.
But wait, what is this max-content
thing? By setting the width
of our two columns to max-content
, we force the browser to give the column just as much space it needs to cram the entire content into the column without messing up the layout by introducing additional line-breaks or so.
In addition, we define a column-gap
and a grid-row-gap
to space the elements out a little bit.
The amount of likes is put into the top left cell by assigning a div
the class .thumbs-up
. The dislikes are placed directly on the right, i.e. in the first row and in the second column.
We take the progress bar from Semantic UI
for convenience and place it in the second row by setting grid-row: 2/ 3
. We instruct Grid
that our progress bar should span
two columns, i.e. the entire width of our grid. Per default, the progress bar has a little bit of margin
at the bottom. Since we don’t want that, we explicitly set margin-bottom
to 0
to tweak Semantic UI
a little bit.
2.6. Finish VideoMetadata component
Cool, now that we have that our of the way, let’s quickly finish our VideoMetadata
component.
Remember that we still need to create the markup for the elements we marked with the red rectangle before!
Please update the render
function of your VideoMetadata
component like so.
We added a new class called .video-actions
which is a flex
container as well. This element basically corresponds to the content that we marked in red in section 2.2. By setting align-items: center
, we center its children vertically. For aesthetic reasons, we specify that each direct descendant of .video-actions
except the last one should have a right margin of 8px
. Like so, we can space the elements out a little bit.
In addition to our Rating
component, we added a few buttons. These buttons are also present in the original Youtube
app. Fortunately, we can use some components that Semantic UI
already provides. Here’s what we have so far. Click on the image to see it in high resolution.

3 Tests
Wow, this tutorial is getting really long. Let’s just finish it off by adding some snapshot tests. Since we basically only added the markup, our tests will be pretty straight forward.
- Create a directory called
__tests__
insideVideoMetadata
- Add a
VideoMetadata.unit.test.js
file inside of the directory you just created. - Create a directory called
__tests__
insideRating
- Add a
Rating.unit.test.js
file inside of the directory you just created.
Note that we are testing two cases here because our VideoMetadata
component expects to receive the prop viewCount
. We test whether our component works with viewCount
and whether it renders if we leave the viewCount prop
out.
Here are our tests for the Rating
component.
Because our Rating
component doesn’t accept props
as of now, we just tests whether it renders.
4 Wrap Up
Wow, that was harder than expected.
Good job, we can now display the video’s meta data in our Watch
component.
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