Из редюссера я получаю номер текущей песни.
Затем я создаю функцию, которая визуально ставит на паузу предыдущую песню.Этот колбек я создаю при каждом изменении номера песни ( так же я пробовал создавать его единожды, но и это не решало проблему).
Дальше я единожды среди всех рендеров вешаю событие 'ended'. В этом событие я вызываю колбек. Мне нужно, чтобы в колбеке был номер текущей песни, который меняется от рендера к рендеру.
Я испытал пару способов: пробовал вызвать колбек, передавая в него номер:
() => {listenerEnd(MusicPanel)}
Также я пробовал дать функции получать MusicPanel из окружения (код ниже), но и это не помогло. Во всех этих случаях колбек вызывался с изначально заложенным окружением.
//Мой текущий код(выбрал только нужные куски)
export const TopPanel = memo(() => {
const /*...*/ MusicPanel = UseSelectorMusic()/*Мой личный селектор, который получает музыку из редюссера*/;
const listenerEnd = useCallback(() => {//Тот самый колбек
try {
if (MusicPanel.PlayingInSite) {
console.log(MusicPanel.NumberOFSong);//Изначальное значение
document.getElementById(`ButtonPauseOFSongInSite${MusicPanel.NumberOFSong - 1}`).style.display = "none";
document.getElementById(`ButtonPlayOFSongInSite${MusicPanel.NumberOFSong - 1}`).style.display = "block";
} else {
document.getElementById(`ButtonPauseOFSongInPost${MusicPanel.NumberOFSong - 1}`).style.display = "none";//
document.getElementById(`ButtonPlayOFSongInPost${MusicPanel.NumberOFSong - 1}`).style.display = "block";
}
(document.getElementById("SongInSiteAudio") as HTMLAudioElement).src = MusicPanel.Dir;
(document.getElementById("SongInSiteAudio") as HTMLAudioElement).play();
} catch (e) {console.log(e)}
/*...*/
}, [MusicPanel.NumberOFSong]);
useEffect( () => {
/*...*/
(document.getElementById("SongInSiteAudio") as HTMLAudioElement).addEventListener('ended',
listenerEnd
);
}, []);
Я смог обойти это, передав в функцию useEffect MusicPanel в массив зависимостей. Это помогает, так как я пересоздаю колбек, но появляется новая проблема, а именно обработчиков событий становится в два раза больше после каждого рендера.
Тогда мой код становится похожим на это:
export const TopPanel = memo(() => {
const /*...*/ MusicPanel = UseSelectorMusic()/*Мой личный селектор, который получает музыку из редюссера*/;
const listenerEnd = useCallback(() => {//Тот самый колбек
try {
if (MusicPanel.PlayingInSite) {
console.log(MusicPanel.NumberOFSong);//Изначальное значение
document.getElementById(`ButtonPauseOFSongInSite${MusicPanel.NumberOFSong - 1}`).style.display = "none";
document.getElementById(`ButtonPlayOFSongInSite${MusicPanel.NumberOFSong - 1}`).style.display = "block";
} else {
document.getElementById(`ButtonPauseOFSongInPost${MusicPanel.NumberOFSong - 1}`).style.display = "none";//
document.getElementById(`ButtonPlayOFSongInPost${MusicPanel.NumberOFSong - 1}`).style.display = "block";
}
(document.getElementById("SongInSiteAudio") as HTMLAudioElement).src = MusicPanel.Dir;
(document.getElementById("SongInSiteAudio") as HTMLAudioElement).play();
} catch (e) {console.log(e)}
/*...*/
}, [MusicPanel.NumberOFSong]);
useEffect( () => {
/*...*/
(document.getElementById("SongInSiteAudio") as HTMLAudioElement).addEventListener('ended',
listenerEnd
);
}, [MusicPanel.NumberOfSong]);/*Теперь я пересоздаю слушатель событий, что раздваивает его после каждого рендера. В JS документации говорится, что при при повтором вызове слушателя событий прошлый затирается, но не в моём случаи, почему-то.*/
Как бы обойти это замыкание?