React Doesn't Update HTML5 Video Sources

I’ve been developing a super simple video player React component lately, based around the HTML5 <video> element. In the development environment provided with create react app the component was working fine, the video was changing in response to React router changes, however in production builds I was encountering a problem. When updating the video source through the component’s props, the video player wasn’t changing.

const Player = ({ id, video, thumbnail }) => (
    <video poster={thumbnail} controls>
        <source src={video} />
    </video>
);

A super simple component right, which at first test appears to work just fine. Ignore the fact that we are only serving a single source & not specifying the format for now.

To understand what’s happening, we need to consider how React handles changing props on HTML components.

For for HTML elements, when the props change React only necessarily applies the attribute changes, it doesn’t necessarily re-render the whole element. We see this optimised behaviour in production builds, but not in development where whole elements are re-rendered from scratch instead.

This meant that in development the change to the thumbnail prop was causing the video element to be re-rendered, but in production builds the element wasn’t. Only the attributes were changed.

We also need to note that if a video source has already been loaded, changing the URL of the src attribute won’t cause a reload of the video; that is unless you’re using dev tools to change the source, in which case a work around is applied to reload the whole video element whenever any of the child source elements change.

Therein lies the solution, we can trigger React to fully re-render the video element (like dev tools does) by changing the key.

const Player = ({ id, video, thumbnail }) => (
    <video key={id} poster={thumbnail} controls>
        <source src={video} />
    </video>
);

In my case as there was a one-to-one mapping between ids and video sources, the id prop made a suitable key, in other cases some id generation based upon the video source URL(s) might be necessary.