Reactjs 将AttachMediaStream与React渲染方法一起使用?

Reactjs 将AttachMediaStream与React渲染方法一起使用?,reactjs,webrtc,skylink,temasys,Reactjs,Webrtc,Skylink,Temasys,我正在将AttachMediaStream集成到使用React的程序中 我可以将媒体流连接到如下元素: var vid = document.getElementById("myVideo"); attachMediaStream(vid, stream); 但这不在React Render方法的范围内,我认为应该发生类似的事情 如果我将它按原样放在React Render方法中,它将在每次Render方法运行时运行 我想到了一种方法: 向组件添加两个变量: 此.MediaStream需要

我正在将AttachMediaStream集成到使用React的程序中

我可以将媒体流连接到如下元素:

var vid = document.getElementById("myVideo");
attachMediaStream(vid, stream);
但这不在React Render方法的范围内,我认为应该发生类似的事情

如果我将它按原样放在React Render方法中,它将在每次Render方法运行时运行

我想到了一种方法:

  • 向组件添加两个变量:
    • 此.MediaStream需要连接
    • 这个是.props.mediaStream
  • 请注意,
    this.mediaStreamNeedsToBeAttached
    不是
    this.state
    this.props
    的一部分。如果是的话,在Render方法中切换它是不合法的
  • 当获得媒体流时,组件:
    • this.MediaStreamNeedsToBeatAttached
      设置为true
    • 运行
      this.setProps({mediaStream:newlyObtainedMediaStream})导致渲染方法运行
  • 渲染方法:
    • 检查
      this.mediaStreamNeedsToBeatAttached
      是否为真
    • 如果是这样,则运行
      attachMediaStream(vid,this.props.mediaStream)
      并切换
      this.mediaStream
我想这会管用的,但我想我应该检查一下这里,看看是否还有其他人有更优雅的解决方案


任何想法或意见将不胜感激

我在这方面也遇到了问题,似乎在访问虚拟dom的方式和
attachMediaStream
的工作方式上存在一些中断

我正在将
MediaStream
对象置于状态,并试图对其调用
attachMediaStream
。。。但不管出于什么原因,它只是没有连接

(我正在使用redux),但概念是一样的):

componentDidMount=()=>{
setTimeout((函数(){
console.log('附加媒体流')
attachMediaStream(this.props.stream,this.video);
}).bind(this),0);
}
render(){
报税表(
{this.video=video;}}/>
)    
}

我使用了一个
ref
()来获取虚拟媒体元素,并在
componentDidMount
中调用它,因为它可以访问DOM,但不修改状态。

更新2018年10月

据了解,React目前与领先的WebRTC服务提供商100%不兼容。到目前为止,我已经与两个WebRTC服务提供商合作过,它们都需要dom元素的ID,并将视频流附加到其中,不是通过React,而是通过直接dom操作。在“反应”(React)渲染上,完成的渲染中间歇性地缺少这些流

间歇性的原因是因为存在比赛条件。React将运行render函数,您的WebRTC代码将订阅视频流并尝试将其附加到由render创建的元素。如果订阅尝试在渲染函数创建某个元素之前将视频流附加到该元素,则该流将从完成的渲染中丢失

根据同一篇文章,解决方案是通过dom操作插入所有与WebRTC相关的dom元素,从WebRTC完全解构React,例如:

        let elDialUIContainer = document.querySelector('#dialComponentUIContainer');

        if (!elDialUIContainer) {
            elDialUIContainer = document.createElement('div');
            elDialUIContainer.setAttribute('id', 'dialComponentUIContainer');
            elDialUIContainer.setAttribute('style', this.styleObjectToString(styles.dialComponentUIContainer));
            elContentContainer.prepend(elDialUIContainer);
        }

       [.....]

        if (localThis.applicationState.remoteVideoStream) {
            console.log('attaching remoteVideoStream to #video' + localThis.applicationState.remoteVideoStream.getId());
            let elOtherCallerVideoStream = document.querySelector('#video' + localThis.applicationState.remoteVideoStream.getId());
            if (!elOtherCallerVideoStream) {
     localThis.applicationState.remoteVideoStream.play('remoteCallerVideo');
            }
        }
……等等。这些元素添加在dom元素中,该元素位于该组件的React render函数生成的元素之上和之外,因此在该渲染函数运行时它们不会受到影响

我有一个函数,
addWebRTCMelements
,它将这些元素添加到dom中。它由
ComponentDidMount()
调用,并且在每次WebRTC事件发生时(例如,远程流进入时)也会调用它

过时:2018年9月更新

下面是另一种方法,使用React
createRef()

  • 获取对视频元素的React ref。在React组件构造函数中:

    this.refToMyVideo=React.createRef()

  • 将html元素附加到此引用。在React render函数中:

  • React createRef上的文档是

    过时:从2017年12月起:

    @jordan,我认为您在“访问虚拟dom的方式和AttachmedAstream的工作方式的不连续性”方面提出了一个很好的观点

    我是这样处理的。到目前为止,它似乎正在发挥作用,尽管可能有一个更优雅的解决方案

    function attachMediaStreamToElement(idToWaitFor, stream){
            const elementExists = $(idToWaitFor).length > 0;
            if (elementExists) {
                const idToWaitForMinusPoundSign = idToWaitFor.replace("#", "");
                var vid = document.getElementById(idToWaitForMinusPoundSign);
                attachMediaStream(vid, stream);
            }
            else {
                setTimeout(function () {
                    attachMediaStreamToElement(idToWaitFor, idToWaitFor, stream)
                }, 50);
            }
        }
    

    一旦流可用,我就调用它。例程等待渲染函数渲染目标元素,然后将流附加到它。

    我尝试了上述方法,但效果不可靠。有时流不会附加到元素。在渲染功能期间,渲染元素可能不是DOM的可靠组成部分。目前我正在使用一个函数,该函数使用
    setTimeout
    轮询所需元素的存在,然后运行
    attachMediaStream
    。我还不确定这是否100%可靠。
    <video ref={this.refToMyVideo}>
    </video>
    
    let vidElement = this.refToMyVideo.current;
    attachMediaStream(vidElement, stream);
    vidElement.onloadedmetadata = function(e) {
      vidElement.play();
    };
    
    function attachMediaStreamToElement(idToWaitFor, stream){
            const elementExists = $(idToWaitFor).length > 0;
            if (elementExists) {
                const idToWaitForMinusPoundSign = idToWaitFor.replace("#", "");
                var vid = document.getElementById(idToWaitForMinusPoundSign);
                attachMediaStream(vid, stream);
            }
            else {
                setTimeout(function () {
                    attachMediaStreamToElement(idToWaitFor, idToWaitFor, stream)
                }, 50);
            }
        }