'React router component not destroying when user leaves the page
I have a video player (jsmpeg player) that opens up a websocket to a server to play live video. The way the video server works is that it counts the number of clients connecting. It starts streaming at clients > 0. This part works. When my video player was in a standalone react-app all by itself it handled everything nicely when I would close the tab/reopen.
I adjusted to using react-router. I want the same sort of logic but instead of opening and closing a tab I'm going to a new react-router page. I have a home page and a player page. When I open the player page it works well, the server realizes a client connects and starts, but when I go back to the home page it "stays alive" and doesn't seem to unmount/end the connection. When I go back to the player page it opens up a second connection, so on and so forth, until I close the tab which terminates all the clients.
How can I close the player when I navigate away from the page? I want navigating off of player.js to function just like closing a tab. The component can re-render/mount when I navigate back to player.
My app.js
import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import Contact from './components/Contact';
import Error from './components/Error';
import Navigation from './components/Navigation';
import Player from './components/Player.js';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigation />
<Switch>
<Route path="/" component={Home} exact/>
<Route path="/player" component={Player}/>
<Route component={Error}/>
</Switch>
</div>
</BrowserRouter>
);
}
}
export default App;
My Player
import React from 'react';
import JsmpegPlayer from './JsmpegPlayer';
import '../App.css';
const videoOptions = {
poster: ''
};
const videoOverlayOptions = {autoplay: true};
const player = () => {
return (
<div>
<header>
<JsmpegPlayer
wrapperClassName="video-wrapper"
videoUrl="ws://<my ip>:9999"
options={videoOptions}
overlayOptions={videoOverlayOptions}
/>
</header>
</div>
);
}
export default player;
The jsmpeg player
import React, {Component} from 'react';
import JSMpeg from '@cycjimmy/jsmpeg-player';
export default class JsmpegPlayer extends Component {
constructor(props) {
super(props);
this.els = {
videoWrapper: null,
};
};
render() {
return (
<div
className={this.props.wrapperClassName}
ref={videoWrapper => this.els.videoWrapper = videoWrapper}>
</div>
);
};
componentDidMount() {
// Reference documentation, pay attention to the order of parameters.
// https://github.com/cycjimmy/jsmpeg-player#usage
console.log('I was triggered during componentDidMount')
new JSMpeg.VideoElement(
this.els.videoWrapper,
this.props.videoUrl,
this.props.options,
this.props.overlayOptions
);
};
};
Solution 1:[1]
You need to destroy your JSMpeg
instance when the component un-mounts. Save the instance when it is created like so this.videoPlayer = new JSMpeg.VideoElement(...)
and then in the componentWillUnmount
call this.videoPlayer.destroy()
You will need to do this for most third party libraries because the instance will continue to live in memory and that can build up over time causing memory leaks
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Andrew Axton |