Reactjs 由于React钩子中依赖项数组内的函数,无限重渲染

Reactjs 由于React钩子中依赖项数组内的函数,无限重渲染,reactjs,react-hooks,node-media-server,Reactjs,React Hooks,Node Media Server,您好,我正在尝试在我的网站上实现实时流媒体视频,因为我使用了node media server,我在这里面临的问题是我的网站陷入无限重渲染,因为我在其中创建了一个播放器。在react挂钩中是否有专门的解决方案。我正在共享一段足以理解问题的代码 const videoRef = useRef(); const {id } = props.match.params; useEffect(() => { props.fetchStream(id); buildPlay(); }

您好,我正在尝试在我的网站上实现实时流媒体视频,因为我使用了node media server,我在这里面临的问题是我的网站陷入无限重渲染,因为我在其中创建了一个播放器。在react挂钩中是否有专门的解决方案。我正在共享一段足以理解问题的代码

 const videoRef = useRef();

const {id } = props.match.params;
useEffect(() => {
    props.fetchStream(id);
   buildPlay();
}, [buildPlay]);

function buildPlay() {
    if(player || !props.stream){
        return ;
    }
    var player = flv.createPlayer({
        type: 'flv',
        url: `http://localhost:8000/live/${id}.flv`
    });
    player.attachMediaElement(videoRef.current);
    player.load();

}
if(!props.stream){
        return <div>Loading...</div>
    }
    return (
        <div>
            <video ref={videoRef} style={{width: "100%"}} controls/>
            <h1>{props.stream.title}</h1>
            <h5>{props.stream.description}</h5>
        </div>
    )
const videoRef=useRef();
const{id}=props.match.params;
useffect(()=>{
props.fetchStream(id);
buildPlay();
},[buildPlay]);
函数buildPlay(){
如果(玩家| |!道具流){
返回;
}
var player=flv.createPlayer({
类型:“flv”,
网址:`http://localhost:8000/live/${id}.flv`
});
player.attachMediaElement(videoRef.current);
player.load();
}
如果(!props.stream){
返回加载。。。
}
返回(
{props.stream.title}
{props.stream.description}
)

导致无限重渲染的原因是组件函数体中声明的所有内容都会在每次渲染时重新声明,因此
buildPlay
是一个新函数,每次渲染时效果都会无限执行。将函数指定为依赖项并不常见(除了
props.callback
可能),但如果确实需要,应该将函数移出组件并对其进行参数化(请参见下面的“显示代码片段并运行”)

查看
buildPlay
,在本例中实际发生变化并应指定为依赖项的是
[props.match.params.id,props.stream,videoRef.current]
。您的效果代码应该如下所示:

const dependencies=[props.match.params.id,props.stream,videoRef.current];
useffect(()=>{
如果(!props.stream | |!videoRef.current)返回;
//在组件外部定义,参数化为buildPlay(id、流、元素)
buildPlay(…依赖项);
//或者在效果中内联
/*如果(玩家| |!道具流){
返回;
}
var player=flv.createPlayer({
类型:“flv”,
网址:`http://localhost:8000/live/${id}.flv`
});
player.attachMediaElement(videoRef.current);
player.load()*/
}依赖关系);
看看下面代码段中的两个React应用程序:第一个采用您的方法,第二个将Dependency函数移到组件外部并将其参数化

const InfiniteRenderApp=()=>{
const[runCount,setRunCount]=React.useState(0);
函数doSomething(){
如果(运行计数<10000){
设置运行计数(运行计数+1);
}否则{
抛出“无限渲染循环,停在这里!”;
}
}
React.useffect(()=>{
试一试{
doSomething();
}捕捉(错误){
设置运行计数(err);
}
},[doSomething]);
返回{runCount};
};
ReactDOM.render(,document.getElementById('infinite-render-app');
函数doSomething(runCount、setRunCount){
设置运行计数(运行计数+1);
}
const GoodApp=()=>{
const[runCount,setRunCount]=React.useState(0);
React.useffect(()=>{
doSomething(运行计数、设置运行计数);
},[doSomething]);
返回{runCount};
};
ReactDOM.render(,document.getElementById('app'))

props.fetchStream
buildPlay
是否会在某个地方更新某些状态,以触发此组件重新招标
buildPlay
似乎没有,所以我怀疑
fetchStream
有。您是否也可以共享父组件,以便我们可以看到哪些道具以及如何传递道具?