Как сделать так, чтобы переменная сохранялась после EventListener в reactJS? - PullRequest
0 голосов
/ 08 мая 2020

У меня проблема с переменными "значками" в моем коде. Он инициализирован и определен в области EventListener, но не определен после этой области, поэтому я получил ошибку при попытке компиляции. Я действительно не знаю, как сделать глобальную переменную в reactJS, и после поиска похоже, что это не рекомендуется делать. Итак, есть ли способ заставить эту переменную работать вне области EventListener, чтобы класс «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;

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Добро пожаловать в stackoverflow!

Как вы узнали, вам не следует создавать глобальные переменные. (В общем, это не лучшая идея)

Вы используете функциональный компонент function App() какой человек вы можете использовать React Hooks

Вы можете использовать useEffect крючок для замены window.onload и useState, чтобы иметь внутреннее состояние для компонента.

Примерно так:

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 для лучшего взаимодействия с пользователем.

0 голосов
/ 08 мая 2020

Я не знаю, правильно ли вы используете событие 'load', я думаю, что вы можете поместить слушателя в DidMount или useEffect в приложении и использовать состояние приложения, передавая компоненту Demo как Параметры:

...