如何在 reactJS 中的 EventListener 之后仍然定义变量?

How to make variable be still defined after EventListener in reactJS?

我的代码中的变量 "icons" 有问题。它在 EventListener 范围内初始化和定义,但未在该范围之后定义,因此我在尝试编译时遇到错误。我真的不知道如何在 reactJS 中创建全局变量,在搜索之后看起来不建议这样做。那么有没有办法让该变量在 EventListener 范围之外工作,以便 class "Demo" 可以使用它?

import React from 'react';
import logo from './logo.png';
import './App.css';
import Skycons from 'react-skycons';

function App() {
  return (
    <div className="App">

        <img src={logo} className="App-logo" alt="logo" />

        <div class="location"> 
    <h1 class="location-timezone"> Lokalizacja </h1>
    <Demo />    
</div>

<div class="temperature">
    <div class="degree-section">

    <h2 class="temperature-degree"> Brak </h2>
        <span> °C </span>
    </div>
    <div class="temperature-description"> Brak </div>

</div>

<div class="sekcja-jutro">
    <h1>Pogoda na Jutro: </h1>
</div>

<div class="minimalna">
    <span>Minimalna:</span>
    <h1 class="temperatura-minimalna"> Brak </h1>
    <span> °C </span> 
</div>

<div class="maksymalna">
    <span>Maksymalna:</span>
    <h1 class="temperatura-maksymalna"> Brak </h1>
    <span>°C</span>
</div>

    </div>


  );
}

window.addEventListener('load',()=> {
    let long;
    let lat;
    let temperatureDescription = document.querySelector(".temperature-description");
    let temperatureDegree = document.querySelector(".temperature-degree");
    let locationTimezone = document.querySelector(".location-timezone");
    let minimalna = document.querySelector(".temperatura-minimalna");
    let maksymalna = document.querySelector(".temperatura-maksymalna");

    if(navigator.geolocation){
            navigator.geolocation.getCurrentPosition(position =>{
                long = position.coords.longitude;
                lat = position.coords.latitude;

                const proxy = "https://cors-anywhere.herokuapp.com/";
                const api = `${proxy}https://api.darksky.net/forecast/1539bbb708779eef3993021296196cb2/${lat},${long}`;

                fetch(api)
            .then(response =>{
                return response.json(); 
            })
            .then(data => {
                console.log(data);
                const {temperature, summary, icon} = data.currently;

                var icons;  //there is initialized
                icons = icon.replace(/-/g, "_").toUpperCase();  //there is defined
                console.log(icons); //There I make it display in console so I see that it works as it should

                temperatureDegree.textContent = temperature;
                let celcjusz = (temperature - 32) * 5/9;
                temperatureDegree.textContent = Math.floor(celcjusz);
                temperatureDescription.textContent = summary;
                locationTimezone.textContent = data.timezone;

                const {temperatureLow} = data.daily.data[1];
                minimalna.textContent = temperatureLow;          
                let celcjusz1 = (temperatureLow - 32) * 5/9;
                minimalna.textContent = Math.floor(celcjusz1);

                const {temperatureMax} = data.daily.data[1];
                maksymalna.textContent = temperatureMax;          
                let celcjusz2 = (temperatureMax - 32) * 5/9;
                maksymalna.textContent = Math.floor(celcjusz2);
            });
            });
        }
    });
      class Demo extends React.Component {
        render () {
          return (
            <Skycons 
              class="icon"  
              color='white' 
              icon={icons}  //There I make display icon as anything is in "icons" variable but after compiling I got error that icons is not defined
              autoplay={true}
              height="130"                 
            />
          )
        }
      }
export default App;

不知道你是否正确使用了'load'事件,我觉得你可以把你的监听器放在App中的DidMount或useEffect中,并使用app的状态,传递给作为参数的组件演示:

欢迎使用 Whosebug!

如您所见,您不应该创建全局变量。 (总的来说,他们不是一个好主意)

您正在使用功能组件function App() which man you can use React Hooks

您可以使用 useEffect 挂钩替换 window.onloaduseState 以获得组件的内部状态。

像这样:

import React, { useEffect, useState } from "react";
import logo from './logo.png';
import './App.css';
import Skycons from 'react-skycons';    
function App() {
  const [state, setState] = useState({
    long: null,
    lat: null,
    temperatureDescription: "",
    temperatureDegree: 0,
    locationTimezone: "",
    minimalna: 0,
    maksymalna: 0,
    icons: ""
  });

  useEffect(() => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(position => {
        // save lat/long to save in state and later use
        const lat = position.coords.latitude;
        const long = position.coords.longitude;
        setState({
          ...state,
          lat,
          long
        });

        const proxy = "https://cors-anywhere.herokuapp.com/";
        const api = `${proxy}https://api.darksky.net/forecast/1539bbb708779eef3993021296196cb2/${lat},${long}`; // <-- use lat/long

        fetch(api)
          .then(response => {
            return response.json();
          })
          .then(data => {
            console.log(data);
            const { temperature, summary, icon } = data.currently;

            const celcjusz = ((temperature - 32) * 5) / 9;

            const { temperatureLow } = data.daily.data[1];
            const celcjusz1 = ((temperatureLow - 32) * 5) / 9;

            const { temperatureMax } = data.daily.data[1];
            const celcjusz2 = ((temperatureMax - 32) * 5) / 9;
            setState({
              ...state,
              temperatureDescription: summary,
              temperatureDegree: Math.floor(celcjusz),
              locationTimezone: data.timezone,
              minimalna: Math.floor(celcjusz1),
              maksymalna: Math.floor(celcjusz2),
              icons: icon.replace(/-/g, "_").toUpperCase() //there is defined
            });
          });
      });
    }
  }, []);

  return (
    <div className="App">
      <img src={logo} className="App-logo" alt="logo" />

      <div class="location">
        <h1 class="location-timezone"> Lokalizacja </h1>
        <Demo icons={state.icons} />
      </div>

      <div class="temperature">
        <div class="degree-section">
          <h2 class="temperature-degree"> Brak </h2>
          <span> {state.temperatureDegree}°C </span>
        </div>
        <div class="temperature-description">
          {" "}
          {state.temperatureDescription}{" "}
        </div>
      </div>

      <div class="sekcja-jutro">
        <h1>Pogoda na Jutro: </h1>
      </div>

      <div class="minimalna">
        <span>Minimalna:</span>
        <h1 class="temperatura-minimalna"> Brak </h1>
        <span> {state.minimalna}°C </span>
      </div>

      <div class="maksymalna">
        <span>Maksymalna:</span>
        <h1 class="temperatura-maksymalna"> Brak </h1>
        <span>{state.maksymalna}°C</span>
      </div>
    </div>
  );
}

class Demo extends React.Component {
  render() {
    return (
      <Skycons
        class="icon"
        color="white"
        icon={this.props.icons} //There I make display icon as anything is in "icons" variable but after compiling I got error that icons is not defined
        autoplay={true}
        height="130"
      />
    );
  }
}
export default App;

我没有测试它是否运行,但理论上这应该是您的目标。请不要 useEffect 在渲染后运行。这意味着如果您愿意,可以在 long!=null 之前显示加载动画或文本以获得更好的用户体验。