我正在玩钩子。我的代码如下:
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
生命周期中使用类组件?
答案 0 :(得分:2)
您必须了解useEffect
的工作原理。
useEffect(() => {
// your code
return () => {
// your clearup code
};
}, [videoProgress]); // => This is the key point. It's called dependency
每当依赖项更改时,请重新运行useEffect
。您的videoProgress
值会在时间间隔后发生变化(可能不超过1秒,我不知道)。这就是为什么react重新运行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。