将类组件重塑为挂钩函数组件

时间:2019-03-06 20:21:14

标签: reactjs

我有一个课堂组件:

import React, { Component, Fragment } from 'react';
import ReactPlayer from 'react-player';

import storage from '../../utils/localStorage';

const STORAGE_VIDEOS_DATA_KEY = 'VIDEOS_DATA';

class VideoItem extends Component  {
  constructor(props) {
    super(props);

    this.state = {
      playingStatus: false,
      videoId: 318298217,
    };
  }

  componentDidMount() {
    window.addEventListener(
      'beforeunload',
      this.saveStateToLocalStorage
    );
  }

  componentWillUnmount() {
    window.removeEventListener(
      'beforeunload',
      this.saveStateToLocalStorage
    );

    this.saveStateToLocalStorage();
  }

  handlePlayingStatus = () => {
    this.seekToPoint();

    this.setState({
      playingStatus: true,
    });
  }

  setVideoProgress = videoProgress => {
    this.setState({
      videoProgress: videoProgress.playedSeconds,
    });
  }

  onVideoPause = () => {
    this.saveStateToLocalStorage();

    this.setState({
      playingStatus: false,
    });
  }

  onVideoEnd = () => {
    console.log('backend call - video end status');
  }

  seekToPoint = () => {
    const { videoId } = this.state;

    const videosData = storage.hasKey(STORAGE_VIDEOS_DATA_KEY) &&
      JSON.parse(storage.getItem(STORAGE_VIDEOS_DATA_KEY));
    const toReturnVideoPoint = videosData[videoId] || 0;
    this.player.seekTo(Number(toReturnVideoPoint));
  }

  saveStateToLocalStorage = () => {
    const { videoProgress, videoId } = this.state;

    const videosPlayedDuration = {
      [videoId]: videoProgress,
    };

    storage.setItem(STORAGE_VIDEOS_DATA_KEY, JSON.stringify(videosPlayedDuration));
  };

  render() {
    const { playingStatus, videoId } = this.state;

    return (
      <Fragment>
        <ReactPlayer
          ref={player => { this.player = player; }}
          playing={playingStatus}
          url={`https://player.vimeo.com/video/${videoId}`}
          onPause={this.onVideoPause}
          onEnded={this.onVideoEnd}
          onProgress={this.setVideoProgress}
        />
        <button onClick={this.handlePlayingStatus}>GO BACK TO THE PREVIOUS POINT</button>
      </Fragment>
    );
  }
}

export default VideoItem;

如您所见,它是一个类组件。我试图对其进行重塑,以减少带有钩子的功能组件的代码。我试过了,但是ComponentDidMount中这里发生的事情被重复了太多次了。

如何停止useEffect挂钩中过多的componentDidMount逻辑渲染?

1 个答案:

答案 0 :(得分:1)

传递一个空数组作为参数,例如:

useEffect(() => {
  window.addEventListener(
    'beforeunload',
    saveStateToLocalStorage
  );

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

使用useEffect时,类似于在同一钩子中使用componentDidMountcomponentDidUpdatecomponentWillUnmount。函数的主体是在挂载组件以及每次接收更新时运行的函数。 return函数是在卸载组件之前运行的。

您可以传递第二个可选参数,即一个值数组,以告诉React仅在渲染之间的某些变量发生更改时才再次运行该函数。当您传递一个空数组时,您只是在告诉React绝对不要更新它。

选中the React Hooks documentation,以了解更多信息。