簡體   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