![](/img/trans.png)
[英]React useEffect causing infinite re-render despite passing argument to dependency array
[英]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.