繁体   English   中英

由于 function 在 React 钩子中的依赖数组内部,无限重新渲染

[英]Infinite re-render due to function inside dependency array in React hooks

嗨,我正在尝试在我的网站中实现实时流媒体视频,为此我使用了节点媒体服务器,我在这里面临的问题是我的网站因为 function 而陷入无限重新渲染,我在其中创建了一个播放器。 有没有专门针对这个反应钩子的解决方案。 我正在分享一段足以理解问题的代码。

 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>
    )

导致无限重新渲染的原因是组件 function 主体中声明的所有内容在每次渲染时都会重新声明,因此buildPlay每次渲染都是新的 function ,并且效果将无限执行。 将 function 指定为依赖项并不常见( props.callback可能除外),但如果你真的想要它,你应该将 function 从组件中移出并参数化它(参见下面的显示代码片段和运行)。

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

const dependencies = [props.match.params.id, props.stream, videoRef.current];
useEffect(() => {
  if (!props.stream || !videoRef.current) return;
  // either defined outside of component, parameterized as buildPlay(id, stream, elem)
  buildPlay(...dependencies);
  // or inlined in the effect
  /* if(player || !props.stream){
        return ;
    }
    var player = flv.createPlayer({
        type: 'flv',
        url: `http://localhost:8000/live/${id}.flv`
    });
    player.attachMediaElement(videoRef.current);
    player.load(); */
}, dependencies);

看看下面片段中的 2 个 React 应用程序:第一个采用您的方法,第二个将依赖 function 移到组件外部并对其进行参数化。

 const InfiniteRenderApp = () => { const [runCount, setRunCount] = React.useState(0); function doSomething() { if (runCount < 10000) { setRunCount(runCount + 1); } else { throw 'Infinite render loop. stop here;'. } } React;useEffect(() => { try { doSomething(); } catch (err) { setRunCount(err), } }; [doSomething]); return <strong>{runCount}</strong>; }. ReactDOM,render(<InfiniteRenderApp/>. document;getElementById('infinite-render-app')), function doSomething(runCount; setRunCount) { setRunCount(runCount + 1), } const GoodApp = () => { const [runCount. setRunCount] = React;useState(0). React,useEffect(() => { doSomething(runCount; setRunCount), }; [doSomething]); return <strong>{runCount}</strong>; }. ReactDOM,render(<GoodApp/>. document;getElementById('app'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script> <div id="infinite-render-app"></div> <div id="app"></div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM