reactjs 检查视频是否已加载,并将其传递给父组件,给出null

pjngdqdw  于 2023-02-22  发布在  React
关注(0)|答案(1)|浏览(155)

我正在尝试查看视频是否已加载并可以在子组件(LandingComponent)中播放,如果已加载,我希望父组件(App)将load设置为true并删除微调器(SpinnerComponent)并显示整个网页。
我总是在父组件中的“video”上得到一个null。即使给予它是否不为null,微调器也会继续无限旋转。进一步检查时,我发现着陆组件也没有得到渲染

import React, { useEffect, useState } from "react";
import NavbarComponent from './Components/Navbar/navbar';
import AboutComponent from './Components/About/about';
import HealthComponent from './Components/Health/health';
import SpinnerComponent from './Components/Spinner/spinner';
import LandingComponent from './Components/Landing/landing';
import ContactUs from './Components/ContactUs/contactUs';
import Footer from './Components/Footer/footer';

function App() {
   const [loaded, setLoaded] = useState(false);

  useEffect(() => { 
    const video = document.getElementById('landing-video');
    console.log('video element:', video); // This is always null
    if (video) {
      video.addEventListener('canplaythrough', () => {
        setLoaded(true);
      });
    }
  }, []);

  return (
    <>
      {loaded ? (
        <>
          <NavbarComponent/>
          <LandingComponent onLoad={() => setLoaded(true)}/>
          <AboutComponent/>
          <HealthComponent/>
          <ContactUs/>
          <Footer/>
        </>
      ) : (
        <SpinnerComponent fullscreen={true} />
      )}
      </>
   
  );
}

export default App;

Landing.js

import React, {useEffect, useLayoutEffect, useRef, useState} from 'react'
import './styleLanding.css';
import AOS from 'aos';
import 'aos/dist/aos.css';
import sample from '../../videos/movie.mp4'

export const LandingComponent = () => {
   console.log('LandingComponent rendered'); // This is also null
  const [loaded, setLoaded] = useState(false);
  const videoRef = useRef(null);

  useEffect(() => {
  AOS.init();
  const video = videoRef.current;
  if (video) {
    video.addEventListener('canplaythrough', () => {
      video.play();
      setLoaded(true);
    });
  }
}, []);

    return (
        <div id="home" className="style-landing" >
          <div className="style-overlay"></div>
           <video ref={videoRef} id="landing-video" src={sample} type={'video/mp4'} preload={'auto'} className="style-video" autoPlay loop muted/>
          <div className="style-content">
            <h2 className="style-heading" data-aos="zoom-in" data-aos-duration="1000" data-aos-offset="130">EXPERIENCE THE BEST</h2>
            <h1 className="style-sub-heading" data-aos="zoom-in" data-aos-duration="1000" data-aos-offset="130">nutrition</h1>
          </div>
          </div>
    )
}

export default LandingComponent
lymnna71

lymnna711#

这里只需要做一些调整。首先,如果我在App.js中解决这个问题,

{loaded ? (
        <>
          <NavbarComponent/>
          <LandingComponent onLoad={() => setLoaded(true)}/>
          <AboutComponent/>
          <HealthComponent/>
          <ContactUs/>
          <Footer/>
        </>
      ) : (
        <SpinnerComponent fullscreen={true} />
      )}

LandingComponent包含在condition中。如果“loaded”状态为真,则只有在此情况下,才会将组件及其html添加(插入)到DOM中

**因为,“loaded”状态最初是假的,视频标记甚至没有插入DOM中。**所以你不能用任何方法捕获元素。你不能通过document.getElementById得到它...所以你的微调器无限显示。
解决方法---

将微调器显示为覆盖层。这样,视频标签将被添加到DOM中,您可以添加侦听器并执行操作。
作为示例,请尝试以下代码以了解...

import { useEffect, useRef, useState } from "react";
import sampleVideo from "./../assets/sample-10s.mp4";

const Practice = () => {
  const vidRef = useRef();

  const [showLoader, setShowLoader] = useState(true);

  useEffect(() => {
    vidRef.current.addEventListener("canplaythrough", () => {
      vidRef.current.muted = true;
      vidRef.current.play();
      setShowLoader(false);
    });
  }, []);

  return (
    <div>
      <div>Hello World</div>

      <video
        ref={vidRef}
        src={sampleVideo}
        type="video/mp4"
        height={400}
        width={500}
      ></video>

      {showLoader && (
        <div
          id="spinnerdiv"
          style={{
            position: "absolute",
            top: 0,
            left: 0,
            width: "100%",
            height: "100%",
            opacity: 0.3,
            backgroundColor: "black",
          }}
        ></div>
      )}
    </div>
  );
};

export default Practice;

在您的代码中,一旦video标签被添加到DOM中,您就可以使用原始代码在子组件中访问它。
主要的问题是LandingComponent一开始就没有出现在DOM中。

相关问题