【问题标题】:Loading gif fades out before the image completely loads, why is that?在图像完全加载之前加载 gif 会淡出,这是为什么呢?
【发布时间】:2020-01-19 22:56:38
【问题描述】:

我正在测试一个虚拟站点以从 NASA API 获取数据。我正在提取数据并输出当天天文图像的标题、日期、作者、说明和网址。一切都完美输出,所以我假设我正确获取了所有内容。

我的另一个任务是在其上运行加载 gif,直到我的所有数据都输出到 DOM 上。文字很快,但图像需要一段时间。我已经顺利地使我的 gif 淡出,但是它淡出的速度比图像加载快。我假设这是因为我正在获取数据,但我对此有点陌生,所以我不确定如何修复它。

我一直在玩 ComponentDidMount() 和 window.eventListener("load", () => {}) 但我认为我使用它的方式并没有按正确的顺序加载所有内容。任何提示将不胜感激!

顺便说一句,我正在使用 React!

App.js

import React, {Component} from 'react';
import DataOutput from './Components/DataOutput'
import LoadingGif from './Components/LoadingGif'

const API_KEY = 'VuPavaR3ZqkuzGivHZJnOPy3KDpjiARyhJsdvcjt'

class App extends Component {
  state = {
    author : undefined,
    date : undefined,
    explanation : undefined,
    title : undefined, 
    url : undefined,
  }

  getNASAData = async () => {
    const getData = await fetch(`https://api.nasa.gov/planetary/apod?api_key=${API_KEY}`)
    const data = await getData.json();
    this.setState({
        author : data.copyright,
        date : data.date,
        explanation : data.explanation,
        title : data.title, 
        url : data.url,
    })
  }

componentDidMount(){
  this.getNASAData();
}

  render() {
    return(
      <div className="App">
       <LoadingGif/>
       <DataOutput 
        title={this.state.title}
        url={this.state.url}
        explanation={this.state.explanation}
        date={this.state.date}
        author={this.state.author}
       />
      </div>
    )
  }
}

export default App;

数据输出.js

import React from 'react'

const DataOutput = props => {
    return (
        <div>
            <div className="container">
                <div className="row mt-5">
                    <div className="col-12">
                        <h1>{props.title}</h1>
                    </div>
                </div>
                <hr/>
                <div className="row mt-5">
                    <div className="col-6">
                        <img className="NasaImg" src={props.url} alt={props.title}/>
                    </div>
                    <div className="col-6">
                        <h2>{props.author}</h2>
                        <h3>{props.date}</h3>
                        <p>{props.explanation}</p>
                    </div>
                </div>
            </div>
        </div>
    )
}

export default DataOutput

加载Gif.js

import React from 'react'
import Cat from '../catLoading.gif'

const LoadingGif = () => {

    window.addEventListener("load", () =>{
        const loader = document.getElementById('loader');
        console.log(loader);
        loader.className += " hidden";
    })

    return (
        <div id="loader" className="loader">
            <img className="catImg" src={Cat} alt="cat loading"/>
        </div>
    )
}

export default LoadingGif

还有 CSS,以防万一……

.NasaImg{
  width:100%;
}

.loader{
  position:fixed;
  z-index:999;
  width: 400px;
  top:0;
  left:0;
  height:100%;
  width:100%;
  background:rgb(223, 217, 224);
  display:flex;
  justify-content:center;
  align-items:center;
}

.loader.hidden{
  animation: fadeOut 1s;
  animation-fill-mode: forwards;
}
.catImg{
  width:400px;
}


@keyframes fadeOut {
  from {
    opacity: 1;
    visibility: visible;
  }
  to {
    opacity: 0;
    visibility: hidden;
  }
}

【问题讨论】:

    标签: reactjs asynchronous fetch-api


    【解决方案1】:

    我不认为你的代码会工作 - 它有多个问题:

    首先,窗口的load 事件可能不会因您的数据请求而触发。

    其次 - 附加事件侦听器是一种“副作用”,您应该将其包装在 useEffect 中。 (但是我们不应该在这里使用那个事件)https://reactjs.org/docs/hooks-effect.html

    React - 尽量避免使用document.find*** 或其他帮助器来获取DOM 节点(同样,通常您不需要直接更改dom 节点)如果您需要访问DOM 节点,请使用@ 987654328@。 https://reactjs.org/docs/refs-and-the-dom.html

    在 React 中,99.99% 的情况下你不应该直接修改 DOM - 让 React 处理 - 你应该为反应组件提供适当的 state 并让你的组件直接渲染。


    好的,我们如何在这里解决您的问题?

    加载 gif 在这一切之上运行,直到我的所有数据都输出到 DOM 上

    因此,我认为我们应该:

    1. 有一个状态标志(比如loaded)来跟踪数据是否已被提取。
    2. loaded 为真时隐藏加载动画。 (假设我们仍在使用 css)

    我们如何做到这一点?

    所以在你的加载器组件中,它应该有一个 prop hidden - 如果它是真的,我们将 hidden 类添加到加载器 - 所以它看起来像这样:

    
    const LoadingGif = ({ hidden }) => {
      return (
        <div id="loader" className={`loader ${hidden ? 'hidden' : ''}`}>
          <img
           //...
          />
        </div>
      );
    };
    

    并在您的App 中添加一个字段到您的状态以跟踪您的数据是否已加载:

    state = {
      // ... your other states
      loaded: false
    };
    

    当您的 fetch 完成后,请务必将其更新为 true

        const data = await getData.json();
          this.setState({
            author: data.copyright,
            date: data.date,
            explanation: data.explanation,
            title: data.title,
            url: data.url,
            loaded: true  // here
          });
    

    在您的渲染中,将 loaded 状态作为道具提供给您的加载器组件:

    // it is hidden when `loaded` is true
    <LoadingGif hidden={this.state.loaded} />
    

    把它放在一起:

    https://codesandbox.io/embed/patient-resonance-s3si9

    【讨论】:

    • 顺便说一下,由于网络请求很快,它仍然会很快消失。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 2012-04-24
    相关资源
    最近更新 更多