【问题标题】:Cannot wrap video.js component in react-loadable无法将 video.js 组件包装在 react-loadable 中
【发布时间】:2019-08-08 06:59:11
【问题描述】:

这里是沙盒链接:https://codesandbox.io/s/playvideo-e3dbw
我正在使用 video.js 在我的 react 项目中显示视频,它被导入到我的 <VideoPlayer/> 组件中。
现在我想用react-loadable 包裹<VideoPlayer/> 因为video.js 太大了。
但是当我在我正在运行的项目中访问实际的视频播放器时,项目崩溃了,我在浏览器的控制台中收到了一些错误消息:

react-dom.development.js:57 Uncaught Invariant Violation: Element type is
invalid: expected a string (for built-in components) or a class/function (for
composite components) but got: object.

Check the render method of `LoadableComponent`.
Warning: Can't perform a React state update on an unmounted component. This is 
a no-op, but it indicates a memory leak in your application. To fix, cancel 
all subscriptions and asynchronous tasks in the componentWillUnmount method.

这是我的一些源代码。在我使用react-loadable 包装<VideoPlayer/> 组件后出现问题,如下所示:

const LoadableVideoPlayer = Loadable({
  loader: () => import('./VideoPlayer'),
  render(loaded, props) {
    let Component = loaded.default;
    return <Component {...props}/>;
  },
  loading: <div>Loading...</div>
});

我想根据当前状态在页面中呈现 pdf 播放器或视频播放器。下面是&lt;LoadableVideoPlayer/&gt;组件的用法:

if (this.state.currentPlayer==='Video' && videoSrc) {
      return <LoadableVideoPlayer key={videoSrc} videoSrc={videoSrc}/>
    } else if (this.state.currentPlayer==='PDF' && pdfSrc) {
      return <PDFPlayer key={pdfSrc} pdfSrc={pdfSrc}/>
    }
}

这是我的&lt;VideoPlayer/&gt; 组件:

import React from 'react';
import videojs from 'video.js';
import 'video.js/dist/video-js.css';

class VideoPlayer extends React.Component {
  componentDidMount() {
    const src = this.props.videoSrc;

    const videoPlayerOptions = {
      controls: true,
      sources:[
        {
          src:src,
          type:'video/mp4'
        }
      ]
    };

    this.player = videojs(this.videoNode, videoPlayerOptions, () => {
      console.log("Ready to play")
    })
  }

  componentWillUnmount() {
    // if (this.player) {
    //   this.player.dispose()
    // }
  }

  render() {
    return(
      <div data-vjs-player style={{width:'100%'}}>
        <video ref={node => this.videoNode = node} className="video-js" />
      </div>
    )
  }
}

export default VideoPlayer

请注意,在componentWillUnmount() 方法中,我注释掉那些代码行,因为如果没有,即使我不使用react-loadable,我也会收到另一条错误消息。
我认为问题可能出在此处,但我搜索了很多并没有找到任何解决方案。

有关更多详细信息,这里是我导入 Loadable 并使用它的地方。

import React from 'react';
import Loadable from 'react-loadable';
import PDFPlayer from './PDFPlayer';

const LoadableVideoPlayer = Loadable({
  loader: () => import('./VideoPlayer'),
  render(loaded, props) {
    let Component = loaded.default;
    return <Component {...props}/>;
  },
  loading: <div>Loading...</div>
});

class ResourcePlayer extends React.Component {
  state = {currentPlayer:'PDF'};

  onPlayerChange = selectedPlayer => {
    this.setState({currentPlayer:selectedPlayer})
  };

  renderPlayer = () => {
    const {videoSrc, pdfSrc} = this.props;

    if (this.state.currentPlayer==='Video' && videoSrc) {
      return <LoadableVideoPlayerkey={videoSrc} videoSrc={videoSrc}/>
    } else if (this.state.currentPlayer==='PDF' && pdfSrc) {
      return <PDFPlayer key={pdfSrc} pdfSrc={pdfSrc}/>
    } else {
      return (
        <div>
          {/*Some placeholder here, not important for this problem*/}
        </div>
      )
    }
  };

  render () {
    // suppose here are some logic to switch the state between 'PDF' and 'Video'
    return (
      {this.renderPlayer()}
    )
  }
}

【问题讨论】:

  • 看到错误,好像是导入组件有问题。您还可以发布您如何导出和导入LoadableComponent
  • 当然,你的意思是LoadableVideoPlayer ?我只是简单地把它放在使用它的正上方。我会把代码贴在问题主要内容里面。
  • 无论哪个组件出现错误,如果您能提供codesandbox link 来重现问题,那就太好了。
  • 感谢您的建议。这里是sanbox链接:codesandbox.io/s/playvideo-e3dbw不知道能不能访问,因为我对code sandbox不熟悉
  • 使用箭头函数进行加载。 link

标签: javascript reactjs video.js react-loadable


【解决方案1】:

我想我找到了原因。而不是在 LoadableVideoPlayer 组件中使用 &lt;div&gt;Loading...&lt;/div&gt; ,我应该使用 react 组件作为加载属性。

const LoadableComponent = () => {
   return <div>Loading...</div>
};

const LoadableVideoPlayer = Loadable({
  loader: () => import('./VideoPlayer'),
  render(loaded, props) {
    let Component = loaded.default;
    return <Component {...props}/>;
  },
  loading: LoadableComponent
});

另外,我错过了一些错误信息,对此我深表歉意。以下是指示此问题的错误消息:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <div />. Did you accidentally export a JSX literal instead of a component?
    in LoadableComponent (created by ResourcePlayer)
    in div (created by ResourcePlayer)
    in ResourcePlayer

【讨论】:

  • 你不需要 react 组件,只需使用 loading: () =&gt; &lt;div&gt;Loading...&lt;/div&gt;codesandbox link 所示
  • 感谢您的出色解决方案!我觉得我在学习 React 方面还有很长的路要走 :)
  • 这里一样芽:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 2021-12-06
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
相关资源
最近更新 更多