繁体   English   中英

如果只有一个状态更新,React 组件不会重新渲染

[英]React component does not re-render if there is only one state update

我有 2 个组件 -> a) VideoJSPlayer 和 b) VideosPage。

顾名思义,VideoJsPlayer 具有视频播放器部分(使用 videojs),VideosPage 使用 VideoJsPlayer 组件显示视频。

每个组件的代码是:

a) VideoJsPlayer

import React, { useEffect } from "react";
import videojs from "video.js";

const VideoJsPlayer = props => {
  let player = null;
  let videoNode = null;

  // Effect for first render only.
  useEffect(() => {
    player = videojs(videoNode, props, function onPlayerReady() {
      console.log("onPlayerReady");
    });
    return function cleanup() {
      if (player) {
        player.dispose();
      }
    };
  }, []);

  return (
    <div>
      <div data-vjs-player>
        <video ref={node => (videoNode = node)} className="video-js"></video>
      </div>
    </div>
  );
};

export default VideoJsPlayer;

b) 视频页面

import React, { useState, useEffect } from "react";
import videojs from "video.js";
import VideoJsPlayer from "../../components/VideoJsPlayer";

const VideosPage = props => {
  const [videoJsOptions, setVideoJsOptions] = useState({});

  // Effect for first render only.
  useEffect(() => {
    let videoJsOptionsTest = {
      autoplay: false,
      controls: true,
      sources: [
        {
          src: "/my-video.mp4",
          type: "video/mp4"
        }
      ]
    };

    console.log("test");

    setVideoJsOptions(videoJsOptionsTest);

    // Cleanup on unmount.
    return function cleanup() {};
  }, []);

  return (
    <React.Fragment>
      <VideoJsPlayer {...videoJsOptions} />
    </React.Fragment>
  );
};

export default VideosPage;

当我检查呈现 VideosPage 组件的 URL 时,我没有看到任何视频。 我假设 VideosPage 中的状态 (videoJsOptions) 尚未更新,因此我没有看到视频。 我可以看到控制台日志 - 不过是“测试”。

当我将 VideosPage 的代码更改为:

import React, { useState, useEffect } from "react";
import videojs from "video.js";
import VideoJsPlayer from "../../components/VideoJsPlayer";

const VideosPage = props => {
  const [videoJsOptions, setVideoJsOptions] = useState({
    autoplay: false,
    controls: true,
    sources: [
      {
        src: "/my-video.mp4",
        type: "video/mp4"
      }
    ]
  });

  // Effect for first render only.
  useEffect(() => {
    /*
    let videoJsOptionsTest = {
      autoplay: false,
      controls: true,
      sources: [
        {
          src: "/my-video.mp4",
          type: "video/mp4"
        }
      ]
    };

    console.log("test");

    setVideoJsOptions(videoJsOptionsTest);
    */

    // Cleanup on unmount.
    return function cleanup() {};
  }, []);

  return (
    <React.Fragment>
      <VideoJsPlayer {...videoJsOptions} />
    </React.Fragment>
  );
};

export default VideosPage;

现在,当我检查呈现 VideosPage 组件的 URL 时,我看到了视频。

我的假设是 - 在第一种情况下,状态更新排队并且永远不会发生。 因为如果真的发生了,它应该重新渲染组件,我应该看到我的视频。

我还尝试更新 VideoJSPlayer 中的 useEffect 以在每次道具更改时运行,但它没有帮助。

对此有何见解?

感谢您的时间。

这是一个沙箱: codeandbox

你有一些错误:

  1. 您不能像那样使用videoNode ,因为 Video.js 使用Ref并且由于您使用的是 React 钩子,因此您需要使用useRef
import React, { useRef, useEffect } from "react"

const VideoJsPlayer = props => {
  const videoRef = useRef(null)

  useEffect(() => {
    //...
    videojs(
      videoRef.current,
      props,
      function onPlayerReady() {
        console.log("onPlayerReady")
      }
    )
   //...
  }, [])

 return (
   <video ref={videoRef} className="video-js" />
 )
}
  1. 您不需要在VideosPage组件中再次使用useEffect ,因为它已经在您的VideoJsPlayer组件中使用过。 您的初始选项需要直接在state或函数外设置,如下所示:
const initialOptions = {
 // ...
}

const VideosPage = () => {
  return <VideoJsPlayer {...initialOptions} />
}

这是一个基于您的代码的有效codeSandbox示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM