【问题标题】:Remodel class component to hooks function component将类组件改造成钩子函数组件
【发布时间】:2019-03-06 20:21:14
【问题描述】:

我有一个类组件:

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 逻辑重新渲染?

【问题讨论】:

    标签: reactjs


    【解决方案1】:

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

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

    当你使用useEffect 时,它类似于在同一个钩子中使用componentDidMountcomponentDidUpdatecomponentWillUnmount。你的函数体是在你的组件被挂载时运行的,在它接收到的每次更新时都会运行。 return 函数是在组件卸载之前运行的函数。

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

    查看the React Hooks documentation 了解更多信息。

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 2021-05-31
      • 2021-09-11
      • 1970-01-01
      • 2020-09-17
      • 1970-01-01
      • 2020-01-23
      • 2020-09-17
      • 2021-01-25
      相关资源
      最近更新 更多