简体   繁体   中英

React: How to add state changing event listeners in hooks?

I am working on a little music component that I found online. Currently now it works fine, but I have tried to make en event listener that toggles a state variable whenever the audio component is playing or no.

Currently I toggle this variable manually, whenever the user clicks a button. But if the user is toggling using play/pause buttons on the keyboard, the state variable for "isPlaying" doesn't change unless I toggle it on the onplay and onpause event listeners.

Unfortunately, this breaks the entire functionality for the hook, and I am nor sure what to do in order to solve it..

Codesandbox here: https://codesandbox.io/s/freaking-music-player-ldxde?file=/src/hooks/useMusicPlayer.js

This is the part that breaks it: [src/hooks/useMusicPlayer.js - line: 7]

useEffect(() => {
    if (state.audioPlayer) {
      //  => Applying these event listeners **** up everything!
      // console.log(state.audioPlayer);
      //   state.audioPlayer.onplay = (event) => {
      //     setState((state) => ({ ...state, isPlaying: true }));
      //   };
      //   state.audioPlayer.onpause = (event) => {
      //     setState((state) => ({ ...state, isPlaying: false }));
      //   };
      state.audioPlayer.onended = event => {
        playNextTrack();
      };
    }
  }, [state, playNextTrack]);

The onended event works fine.. No trouble whatsoever.. But the other ones are messing up the experience.

UPDATE: Moving setState out of useEffect

Adding this method:

  function togglePause() {
    setState((state) => ({
      ...state,
      isPlaying: state.audioPlayer ? !state.audioPlayer.paused : false,
    }));
  }

And updating the useEffect

  useEffect(() => {
    if (state.audioPlayer) {
      console.log(state.audioPlayer);
      state.audioPlayer.onplay = (event: Event) => {
        togglePause();
      };
      state.audioPlayer.onpause = (event: Event) => {
        togglePause();
      };
      state.audioPlayer.onended = (event: Event) => {
        playNextTrack();
      };
    }
  }, [state, playNextTrack]);

This however still causes issues..

Clarification on the actual issue itself

Once the first state.audioPlayer has ended , the event listeners aren't transferred to the next Audio Component, whereas by NOT having the onplay and onpause listeners written in useEffect , the onended is indeed created anew and it works..

There wasn't an actual issue with the code itself. It boils down to the various event handlers. The onpause event is implicitly triggered by the onended which caused multiple state changes to happen in the same event.

The codesandbox is now fully working.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM