Hi I am trying to implement live streaming video in my website, For that i have used node media server, The problem i am facing here is my website get caught into infinite re-rendering because of function in which I have created a player. Is there any solution for this specially in react hooks. I am sharing a piece of code sufficient to understand the problem.
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>
)
What is causing infinite re-renders is that everything declared in a component function body is re-declared on every render, so buildPlay
is a new function every render, and the effect will execute infinitely. It's not really common to specify a function as a dependency (except a props.callback
maybe), but if you really want it, you should move the function out of the component and parameterize it (see show code snippet & run below).
Looking at buildPlay
, what actually changes and should be specified as dependencies in this case is [props.match.params.id, props.stream, videoRef.current]
. Your effect code should look like:
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);
Have a look at the 2 React apps in the snippet below: the first one takes your approach, the second one moves the dependeny function outside the component and parameterizes it.
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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.