我现在正在玩钩子。我的代码看起来像这样:
import React, { Fragment, useState, useEffect, useRef } from 'react';
import ReactPlayer from 'react-player';
import storage from '../../utils/localStorage';
const STORAGE_VIDEOS_DATA_KEY = 'VIDEOS_DATA';
const VideoItem = () => {
const [ playingStatus, setPlayingStatus ] = useState(false);
const [ videoId ] = useState(318298217);
const [ videoProgress, setVideoProgress ] = useState(0);
const player = useRef();
useEffect(() => {
window.addEventListener(
'beforeunload',
saveStateToLocalStorage
);
return () => {
window.removeEventListener(
'beforeunload',
saveStateToLocalStorage
);
saveStateToLocalStorage(); // this needs to be fired only once when component onmounts but clearing effect is done every time videoProgress changes
};
}, [videoProgress]);
const onVideoEnd = () => {
console.log('backend call - video end status');
};
const seekToPoint = () => {
const videosData = storage.hasKey(STORAGE_VIDEOS_DATA_KEY) &&
JSON.parse(storage.getItem(STORAGE_VIDEOS_DATA_KEY));
const toReturnVideoPoint = videosData[videoId] || 0;
player.current.seekTo(Number(toReturnVideoPoint));
};
const saveStateToLocalStorage = () => {
const videosPlayedDuration = {
[videoId]: videoProgress,
};
storage.setItem(STORAGE_VIDEOS_DATA_KEY, JSON.stringify(videosPlayedDuration));
};
return (
<Fragment>
<ReactPlayer
ref={player}
playing={playingStatus}
url={`https://player.vimeo.com/video/${videoId}`}
onPause={() => {
saveStateToLocalStorage();
setPlayingStatus(false);
}}
onEnded={onVideoEnd}
onProgress={progress => setVideoProgress(progress.playedSeconds)}
/>
<button onClick={() => {
seekToPoint();
setPlayingStatus(true);
}}
>
GO BACK TO THE PREVIOUS POINT
</button>
</Fragment>
);
};
export default VideoItem;
我希望仅在组件卸载时清除我的效果,而不是在videoProgress状态发生变化时每次组件都被重新渲染。我可以使用空数组而不是[ videoProgress ]
,但是videoProgress
方法中的saveStateToLocalStorage
将不会更新,并且onPause
方法不会导致正确保存到localStorage(它将保存0)。有没有办法用钩子而不是使用componentWillUnmount
生命周期的类组件?
你必须了解useEffect
的工作原理。
useEffect(() => {
// your code
return () => {
// your clearup code
};
}, [videoProgress]); // => This is the key point. It's called dependency
每当依赖变化时,反应重新运行useEffect
。你的videoProgress
值会在时间间隔后发生变化(可能在1秒之后,我不知道)。这就是为什么反应重新运行useEffect。
你可以这样做。
useEffect(() => {
// your code
return () => {
// your clearup code. =>> This block will work as componentWillUnmount
};
}, []); // => No Dependency
或者您可以添加视频ID的依赖关系(根据您的要求)。
useEffect(() => {
// This block (before the return) will act as componentDidMount
return () => {
// This block will work as componentWillUnmount
};
}, []); // => beacase of No Dependency
单面注意:您可以拥有多个useEffect。