我目前在 nextJS 项目中使用 TypeScript。我使用的是 CDN 版本的 flowplayer,通过钩子添加到页面中。
我在组件的全局范围内有一个变量:视频。
我正在使用 useScript 钩子来加载它。 - https://usehooks.com/useScript/
const status = useScript(
'//cdn.flowplayer.com/players/433ff492-dbea-4527-9f9f-6dd08bc3b0be/native/flowplayer.async.js',
);
当状态变为就绪时,此效果被激活:
useEffect(() => {
function renderFlowPlayer() {
window.flowplayer?.cloud?.then(() => {
video = window.flowplayer('#flowplayer');
video.on('pause playing timeupdate ended', stateHandler);
console.log(video);
});
}
renderFlowPlayer();
return () => {
if (video) {
video.off('pause', stateHandler);
video.off('playing', stateHandler);
video.off('timeupdate', stateHandler);
video.off('ended', stateHandler);
video.destroy();
}
};
}, [status === 'ready]);
flowplayer.cloud.then 在脚本准备好后被添加到 window 对象中。
这是我的 stateHandler 函数:
function stateHandler(ev) {
if (ev.type === 'pause') { console.log('paused'); }
if (ev.type === 'playing') { console.log(`Playing at ${event.target.currentTime}, duration is:
${event.target.duration}, video ID is: ${event.target.opts.metadata.id}`); }
if (ev.type === 'timeupdate') { console.log(event.target.currentTime); }
if (ev.type === 'ended') { console.log('The end'); }
所有console.log 调用首先正确打印值,但是如果我转到另一页并返回,则所有内容都会重复打印。 我猜这些事件监听器没有被正确杀死。 当组件即将卸载时,删除所有这些侦听器的正确方法是什么?
提前致谢!
组件的完整代码如下:
import React, { useState, useEffect } from 'react';
import useScript from '@components/customHooks/useScript';
const SOURCES = ['b8302bc5-0f5f-4de6-a56e-6c05a9cd6025', '03513ba8-ea10-4c41-8f0b-82ab134b995c'];
let video = null;
export default function FlowPlayerWrapper() {
const [demoSrc, setDemoSrc] = useState(SOURCES[0]);
const status = useScript(
'//cdn.flowplayer.com/players/433ff492-dbea-4527-9f9f-6dd08bc3b0be/native/flowplayer.async.js',
);
function stateHandler(ev : FlowPlayerEvent) {
const Event = ev.target;
if (ev.type === 'pause') { console.log('pausado'); }
if (ev.type === 'playing') { console.log(`Tocando em ${Event.currentTime} e a duração é: ${Event.duration} e o id do vídeo: ${Event.opts.metadata.id}`); }
if (ev.type === 'timeupdate') { console.log(Event.currentTime); }
if (ev.type === 'ended') { console.log('Fim'); }
}
useEffect(() => {
function renderFlowPlayer() {
window.flowplayer?.cloud?.then(() => {
video = window.flowplayer('#flowplayer');
video.setSrc(demoSrc);
video.on('pause playing timeupdate ended', stateHandler);
console.log(video);
});
}
renderFlowPlayer();
return () => {
if (video) {
video.off('pause', stateHandler);
video.off('playing', stateHandler);
video.off('timeupdate', stateHandler);
video.off('ended', stateHandler);
video.destroy();
}
};
}, [status === 'ready']);
const togglePlay = () => {
if (!video) return;
video.togglePlay();
};
const toggleSrc = () => {
if (!video) return;
const nextIndex = SOURCES.indexOf(demoSrc) + 1;
video.setSrc(SOURCES[nextIndex] || SOURCES[0]);
};
const toggleMute = () => {
if (!video) return;
video.toggleMute();
};
const toggleExtra = () => {
if (!video) return;
video.currentTime += 20;
};
const toggleFullScreen = () => {
if (!video) return;
video.toggleFullScreen();
};
return (
<div>
<div>
Script status:
{' '}
<b>{status}</b>
</div>
<div id="flowplayer" data-player-id="afe735a8-5e21-4f91-9645-1ca2a6f4541d" />
<div className="row">
<div className="column">
<h2>Chamadas API</h2>
<button type="button" onClick={togglePlay}>Tocar / Pausar</button>
<button type="button" onClick={toggleMute}>Mute / Unmute</button>
<button type="button" onClick={toggleExtra}>Acrescentar 20s</button>
<button type="button" onClick={toggleFullScreen}>Full screen</button>
<button type="button" onClick={toggleSrc}>Mudar vídeo</button>
</div>
</div>
</div>
);
}
答案 0 :(得分:1)
我已经用这个钩子修复了它:
useEffect(() => {
function renderFlowPlayer() {
// Função que está disponível após o script estar carregado e executando
window.flowplayer?.cloud?.then(() => {
video = window.flowplayer('#flowplayer');
// id do video é settado na próxima linha
video.setSrc(demoSrc);
video.on('pause playing timeupdate ended', stateHandler);
});
}
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
renderFlowPlayer();
}
return () => {
if (video) {
video.off('pause', stateHandler);
video.off('playing', stateHandler);
video.off('timeupdate', stateHandler);
video.off('ended', stateHandler);
video.destroy();
}
};
}, [status === 'ready']);
仅在状态就绪时运行效果,而不是在安装阶段完成时运行。 https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables