Hardik Poudel
Hardik Poudel

Reputation: 145

How to display multiple video streams in react?

I am trying to display multiple video streams by appending video to an array and using .map to render videos. If I use the following approach I get the error "Unhandled Rejection (TypeError): Cannot set property 'srcObject' of null". How do I append and display multiple video streams in React?

import React, {useState, useEffect} from 'react';
import {View} from 'react-native';


function createVideo(stream){
    const localVideo = React.createRef();
    localVideo.current.srcObject = stream;
    return(
        <View>
            <video style = {{height: 100, width: 100}} ref = {localVideo} autoPlay />
        </View>
    )
}

const Test = () =>{
    const videos = [];


    navigator.mediaDevices.getUserMedia({video: true}).then(stream => {
        videos.push(createVideo(stream));
    })

    return(
        <View> 
            {
                videos.map(data => data)
            }
        </View>
    )
}

export default Test;

Upvotes: 2

Views: 2800

Answers (1)

windowsill
windowsill

Reputation: 3649

Any code in the function body of a component will run on every render (it's part of the render loop).

Untested:

const Video = ({ stream }) => {
  const localVideo = React.createRef();

  // localVideo.current is null on first render
  // localVideo.current.srcObject = stream;

  useEffect(() => {
    // Let's update the srcObject only after the ref has been set
    // and then every time the stream prop updates
    if (localVideo.current) localVideo.current.srcObject = stream;
  }, [stream, localVideo]);

  return (
    <View>
      <video style={{ height: 100, width: 100 }} ref={localVideo} autoPlay />
    </View>
  );
};

const Test = () => {
  // This would run on every render
  // const videos = [];

  const [streams, setStreams] = useState([]);

  useEffect(() => {
    // This shouldn't run on every render either
    navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
      setStreams([...streams, stream]);
    });
  }, []);

  return (
    <View>
      {
        streams.map(s => <Video stream={s} />)
      }
    </View>
  )
}

export default Test;

Upvotes: 1

Related Questions