我无法在正在使用的帮助器方法中看到更新后的状态。所有这些都在基于类的组件中工作,但是在使用钩子时似乎并不相同。查看我的评论。
import React, { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import ReactPlayer from 'react-player';
import { VIMEO_URL } from '../../consts/urls';
import storage from '../../utils/localStorage';
const STORAGE_VIDEOS_DATA_KEY = 'VIDEOS_DATA';
import './VideoItem.scss';
const VideoItem = ({ vimeoId }) => {
useEffect(() => {
window.addEventListener(
'beforeunload',
saveStateToLocalStorage
);
return () => {
window.removeEventListener(
'beforeunload',
saveStateToLocalStorage
);
saveStateToLocalStorage();
};
}, []);
const [ videoProgress, setVideoProgress ] = useState(0);
const saveStateToLocalStorage = () => {
const videosPlayedDuration = {
[vimeoId]: videoProgress, // here I'm not getting updated videoProgress state, only default value
};
// here I will save videosPlayedDuration to the storage
};
return createPortal(
<div className="video-modal-background" onClick={onVideoClose}>
<div className="video-modal-window">
<ReactPlayer
playing={true}
url={VIMEO_URL + vimeoId}
onProgress={videoProgress => setVideoProgress(videoProgress.playedSeconds)} // here I'm setting state
/>
</div>
</div>,
document.getElementById('modal-root')
);
};
export default VideoItem;
所以正如您所看到的,我正在尝试使用更新状态,但是我得到的只是默认状态0。
答案 0 :(得分:1)
该问题是由于关闭引起的。由于效果仅在初始渲染上运行,因此侦听器持有saveStateToLocalStorage
的引用,该引用仅在初始渲染时从其关闭获取状态值,因此更新后的值在其中不可见。
每当videoProgress
状态更改时,您都需要删除并添加侦听器。为此,您可以将videoProgress
作为第二个参数传递给useEffect
const VideoItem = ({ vimeoId }) => {
const [ videoProgress, setVideoProgress ] = useState(0);
useEffect(() => {
window.addEventListener(
'beforeunload',
saveStateToLocalStorage
);
return () => {
window.removeEventListener(
'beforeunload',
saveStateToLocalStorage
);
saveStateToLocalStorage();
};
}, [videoProgress]);
function saveStateToLocalStorage(){
const videosPlayedDuration = {
[vimeoId]: videoProgress,
};
};
return createPortal(
<div className="video-modal-background" onClick={onVideoClose}>
<div className="video-modal-window">
<ReactPlayer
playing={true}
url={VIMEO_URL + vimeoId}
onProgress={videoProgress => setVideoProgress(videoProgress.playedSeconds)} // here I'm setting state
/>
</div>
</div>,
document.getElementById('modal-root')
);
};
export default VideoItem;
答案 1 :(得分:1)
如果您希望拥有componentWillUnmount
的行为,请使用useRef访问监听器中的更新值:
const [ videoProgress, setVideoProgress ] = useState(0);
const videoProgressRef = useRef(videoProgress);
useEffect(() => videoProgressRef.current = videoProgress, [videoProgress]);
function saveStateToLocalStorage(){
const videosPlayedDuration = {
[vimeoId]: videoProgressRef.current,
};
}
useEffect(() => {
window.addEventListener(
'beforeunload',
saveStateToLocalStorage
);
return () => {
window.removeEventListener(
'beforeunload',
saveStateToLocalStorage
);
saveStateToLocalStorage();
};
}, []);
如果仅在saveStateToLocalStorage
内部使用useEffect
,最好将其移至useEffect
的回调中。这样就不会在每个渲染器上都重新创建它:
useEffect(() => {
function saveStateToLocalStorage(){
const videosPlayedDuration = {
[vimeoId]: videoProgressRef.current,
};
}
window.addEventListener(
'beforeunload',
saveStateToLocalStorage
);
return () => {
window.removeEventListener(
'beforeunload',
saveStateToLocalStorage
);
saveStateToLocalStorage();
};
}, []);