如何在React中删除异步组件?

时间:2018-10-01 18:46:08

标签: javascript reactjs

我有一个通过导入处理异步事件的组件,该导入处理父组件中的click事件。父组件侦听dom元素的单击并启动其this.handleMovieClick(event, 'movie name')处理程序。

父级将closeVideo属性传递给异步加载的子级组件。在子组件中,它会侦听单击以关闭自身或在视频播放完毕时单击。它调用其this.handleVideoEnd(),然后调用this.props.closeVideo

this.props.closeVideo进入父级组件,并调用父级的this.handleCloseVideo()

我的问题是,当不再需要异步加载的组件时,该如何删除它?现在它位于DOM中。有没有一种方法可以强制删除组件?是否可以使用asyc呼叫componentWillUnmount

还是加载组件异步仅对代码拆分有用-根据需要加载所需的代码?这不是要从父级中删除组件吗?但是,React Router如何做到这一点?

父组件:

ParentComponent扩展了组件{

constructor(props) {
 // bind event handlers

//用于保存对异步子加载组件的引用     this.state = {       AnimatedFullScreenMovie:null,       animationFullScreenMoviePath:null      };

  }


handleCloseVideo() {
    this.setState({
      AnimatedFullScreenMovie: null,
      animatedFullScreenMoviePath: null
    })
  }

}

// handles loading the component async, sets the path to movie based on what clicked
handleViewMovieClick(event, name) {
    event.preventDefault();
    if (this.state.AnimatedFullScreenMovie === null) {
      import('./../../../reusable/AnimatedFullScreenMovie').then(component => 
     {
       if (name === 'movie1') {
          this.setState({
              AnimatedFullScreenMovie: component,
              animatedFullScreenMoviePath: "movie1.mp4"
            });
       } else {
          this.setState({
              AnimatedFullScreenMovie: component,
              animatedFullScreenMoviePath: "movie2.mp4"
            });
       }
     }
  }

在父组件的render()中:

  render() {
// if the this.state.AnimatedFullScreenMovie has a component, render it
const showProfileVideo = () => {
      if (typeof this.state.AnimatedFullScreenMovie !== undefined && this.state.AnimatedFullScreenMovie !== null) {
        const AnimatedFullScreenMovie = this.state.AnimatedFullScreenMovie.default;
        return (<AnimatedFullScreenMovie
          videoSrc={this.state.animatedFullScreenMoviePath}
          closeVideo={this.handleCloseVideo} // <-- pass the handleCloseVideo() as a prop to the async loaded child
        />);
      } else {
        return null;
      }
    }

return(
   <section className="video-slider">
    { showProfileVideo() }
<div>
  <p><a href="#" onClick={() => this.handleViewMovieClick(event, 'movie1')}>Watch the film</a></p>
</div>

<div>    
  <p><a href="#" onClick={() => this.handleViewMovieClick(event, 'movie2')}>Watch the film</a></p>
 </div>

     );

}

这是子异步组件:

export default class AnimatedFullScreenMovie extends Component {

  constructor(props) {
    super(props);

    this.videoContainer, this.video;
    this.playVideo = this.playVideo.bind(this);
    this.handleVideoEnd = this.handleVideoEnd.bind(this);
    this.handleClose = this.handleClose.bind(this);
  }

  componentDidMount() {
    this.video.addEventListener('ended', this.handleVideoEnd);
  }

  playVideo() {
    this.video.play();
  }

  handleVideoEnd() {
    this.video.pause();
    this.props.closeVideo; // <- launch the event handler in the parent to close the video by setting this.state.AnimatedFullScreenMovie to null
  }

  handleClose() {
    this.handleVideoEnd()
  }

  componentWillUnmount() {
    this.video.removeEventListener('ended', this.handleVideoEnd);
  }

  render() {
    return (
      <div id="animated-fullscreen-video-wrapper" ref={videoContainer => this.videoContainer = videoContainer}>
        <h2 onClick={this.handleClose}>Close</h2>
        <video src={this.props.videoSrc} ref={video => this.video = video} />
      </div>
    );
  }

}

1 个答案:

答案 0 :(得分:0)

我没有使用this.props.closeVideo正确调用该函数。正确的方法是在异步子组件中使用this.props.closeVideo()

export default class AnimatedFullScreenMovie extends Component {

  // previous code

  handleVideoEnd() {
    this.video.pause();
    this.props.closeVideo(); // <- need to have the '()' chars in order to call
  }

 // remainder code


}