why does the player with custom controls keep working?

Viewed 39

I have a player application that has a problem with unloading itself when the link changes (react routing). On the first load www.host/video everything is fine, but when exiting /video, the player events (play/pause on space) player continue to work on all pages. When I returning to the www.host/video page, the player loads the styles from the player.scss but does not respond to clicks, and the first player also continues to respond to events. The player is not displayed in the dom but the jsxPlayer.js continues to work.

How do I unmount a component when pathname is not equal to "/video"?

jsxPlayer.js

import React from 'react';

import "./../player/player.scss"
class Player extends React.Component {
constructor(props) {
    super(props)
}

componentDidMount() {
    if (window.location.pathname == "/video") {
        import ("./../player/player.js")
    }
}

componentWillUnmount() {
    if (window.location.pathname != "/video") { 
    // what i must to do here?
    }
}

render() {
    return (
        <div>
            <video id="Player" src="./video.mp4" ></video>
            <div className="timeLines"></div>
            <div className="playerController">

                <button id="play">Play</button>

                <input id ="volume" type="range" ></input>
            </div>
        </div>    
    )
} } export default Player;

video.js

import Player from './components/player.js';


class Video extends React.Component {
constructor(props) {
       super(props)
}

render() {
    return (
        <div className="dokoaPlayer">
            <Player />
        </div>
       )
    }
} export default Video

player.js

document.querySelector('#play').onclick = play;
document.querySelector('#volume').oninput = videoVolume;

let Player = document.querySelector('#Player')

function play() {
    if (!(Player.currentTime > 0 && !Player.paused && !Player.ended)) {
        Player.play();
} else {
    Player.pause();
} }

App.js

import AppRoutes from './AppRoutes';
const App = () => {
    return (
            <Routes>
                {AppRoutes.map((route, index) => {
                    const { element, ...rest } = route;
                    return <Route key={index} {...rest} element=  {element} />;
                })}
            </Routes>
    );
}

AppRoutes.js

   const AppRoutes = [

    {
      index: true,
      element: <Home />
      },
      {
       path: '/home',
       element: <Home />
      },
      {
       path: '/video',
       element: <Video />
      },
     ];
     export default AppRoutes;

index.js

root.render(
<div>
    <BrowserRouter>
        <Header />
        <App />
        <Footer />
    </BrowserRouter>
</div>

);

1 Answers

So basically I'm a bit lost in your code:

  1. You mix functional and class components
  2. You have a file player.js, which isn't a react component at all, and you import it in video.js, but somehow your app is behaving like you imported jsxPlayer.js

Besides that, the issue lies in your player.js file, because:

  1. You reference your DOM by document.querySelector, this should be done by adding useRef to your components
  2. You are not cleaning up your .onclick and .oninput events

To fix your issue, you should clean up your event listeners:

componentWillUnmount() {
    // the below line could also be a mistake, 
    // because a component could be unmount before the URL changes, 
    // so this would not fire because window.location.pathname is still "/video"
    // keep in mind that componentDidMount fires when your component renders to the screen
    // and componentWillUnmount fires right before it disappears from the screen
    // so when the URL changes to "/video", react-router renders your components
    // thus there is no need to check for the window.location.pathname
    // if (window.location.pathname != "/video") {
    // what i must to do here?
    document.querySelector('#play').onclick = null;
    document.querySelector('#volume').oninput = null;
    // }
}

I think it should work right away but it is not clean way to do it

Related