使用钩子看不到方法辅助函数内部的状态

Mur*_*ami 5 reactjs react-hooks

我看不到我正在使用的辅助方法内部的更新状态。所有这些都在基于类的组件中工作,但在使用钩子时似乎不一样。看看我的评论。

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;
Run Code Online (Sandbox Code Playgroud)

所以正如你所看到的,我正在尝试使用更新的状态,但我得到的所有状态都是 0 作为默认状态。

Uji*_*T34 3

如果您想让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();
    };
  }, []);
Run Code Online (Sandbox Code Playgroud)

如果您saveStateToLocalStorage仅在内部使用useEffect,最好将其移至 的回调内部useEffect。所以它不会在每次渲染时都重新创建:

  useEffect(() => {
    function saveStateToLocalStorage(){
        const videosPlayedDuration = {
          [vimeoId]: videoProgressRef.current, 
        };
    }

    window.addEventListener(
      'beforeunload',
      saveStateToLocalStorage
    );

    return () => {
      window.removeEventListener(
        'beforeunload',
        saveStateToLocalStorage
      );

      saveStateToLocalStorage();
    };
  }, []);
Run Code Online (Sandbox Code Playgroud)