Creating youtube shorts component in react-native

Hyo
dooboolab
Published in
3 min readJul 24, 2022

The current story shares a brief approach to making apps like Youtube shorts in React Native.

I chose to use react-native-youtube-iframe here since there is an issue with mounting multiple videos in android with react-native-youtube.

Let’s see how to code right away.

1. Wrap component with FlatList

<FlatList
ref={flatListRef}
data={items}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
keyExtractor={item => item?.id}
onEndReached={onEndReached}
renderItem={useCallback(
({item, index}: {item: Item<T>; index: number}) => {
return (
<ReelItem
// TODO
/>
);
},
[layout, visibleIndex],
)}
pagingEnabled
/>

Since FlatList extends the ScrollView, you can use pagingEnabled props to implement paging.

2. Write ShortItem which is a component for playing youtube shorts

type ShortItemProps = {
index: number;
visible: boolean;
playing: boolean;
paused: boolean;
url: string;
layout: LayoutRectangle;
};
function ShortItem({visible, playing, url, layout}: ShortItemProps) {
const youtubeId = getYoutubeIdFromURL(url);
const youtubePlayerRef = useRef<YoutubeIframeRef>(null);
return (
<YoutubePlayer
ref={youtubePlayerRef}
height={layout.height}
width={layout.width}
videoId={youtubeId}
play={playing}
onChangeState={event => {
if (event === 'ended' && visible) {
youtubePlayerRef?.current?.seekTo(0, true);
}
}}
webViewProps={{
injectedJavaScript: `
var element = document.getElementsByClassName('container')[0];
element.style.position = 'unset';
true;
`,
}}
/>
);
}
export default ShortItem;
  • In onChangeState, play time seeks to 0 and continuously loops.
  • In webViewProps, I injected javascript in order to view the video in fullscreen. You can see the related issue here.

3. Check the focused video to handle which video should play

https://user-images.githubusercontent.com/27461460/180647895-b20d2a90-cb01-43a6-abd4-5fb913556fd1.mov

If you see the shorts like the above link, the shorts is only playing the focused video. To achieve that I use viewabilityConfig and onViewableItemsChanged in FlatList. I used the below values and it worked great.

const viewabilityConfig = {
viewAreaCoveragePercentThreshold: 50,
};
  • viewAreaCoveragePercentThreshold: Percent of viewport that must be covered for a partially occluded item to count as “viewable”, 0–100. Fully visible items are always considered viewable. A value of 0 means that a single pixel in the viewport makes the item viewable, and a value of 100 means that an item must be either entirely visible or cover the entire viewport to count as viewable.
const onViewRef = useRef((viewableItems: any) => {
if (viewableItems?.viewableItems?.length > 0) {
const index = viewableItems?.viewableItems?.[0]?.index;
setVisibleIndex(index);
}
});
...viewabilityConfig={viewabilityConfig}
  • The visibleIndex value is saved in react state variable. Therefore we know which item the user is watching.

4. Parse the youtube id from the URL

export const getYoutubeIdFromURL = (url: string): string | undefined => {
if (url.includes('?')) {
const arr = url.split('?');
arr.pop();
url = arr[0];
}

const arr = url.split(/(vi\/|v%3D|v=|\/v\/|youtu\.be\/|\/embed\/)/);
const youtubeId = undefined !== arr[2] ? arr[2].split(/[^\w-]/i)[0] : arr[0];
if (youtubeId.includes('https://youtube.com/shorts/')) {
return youtubeId.replace('https://youtube.com/shorts/', '');
}
return youtubeId;
};

The react-native-youtube-iframe need videoId props to play the youtube video. Since the youtube URL is more widely used, I parsed the youtube URL and get extracted youtubeId.

5. Prepare the data

type Item = {
id: string;
url: string;
};
const items: Item[] = [
{
id: '001',
url: 'https://youtube.com/shorts/Uj74798gItc',
},
{
id: '002',
url: 'https://youtube.com/shorts/HXyx8Sr5RTQ',
},
{
id: '003',
url: 'https://youtube.com/shorts/QgAA_5IPNIs',
},
{
id: '004',
url: 'https://youtube.com/shorts/GFAa6l5zbHE',
},
{
id: '005',
url: 'https://youtube.com/shorts/-IcYublDy7I',
},
{
id: '006',
url: 'https://youtube.com/shorts/6a1tmHi6d60',
},
{
id: '007',
url: 'https://youtube.com/shorts/8Lt1hJnEcq0',
},
{
id: '008',
url: 'https://youtube.com/shorts/266xNTZN5VI',
},
{
id: '009',
url: 'https://youtube.com/shorts/xZ48_razkME',
},
{
id: '010',
url: 'https://youtube.com/shorts/qoM9tP69USo',
},
];
Pass data to [Shorts] props.

6. Finally use @dooboo/react-native-youtube-iframe to handle the player.

When the short item is visible or hidden, we need to pause the video or play the video. However, react-native-youtube-iframe did not support this.

Therefore, I created a PR to handle this and I am using my own package until this will get merged.

Final Result.

The full source code is here. Hope my sample example helps some readers 🙌.

--

--