在 map() 中反应 CSStransition 或 React-spring

问题描述

有人能解释一下如何使用 Csstransiton 或 react-spring 动画制作像 opacity 0 - opacity 1 这样的平滑过渡,当数据来自服务器并且我正在做地图 div 时,会立即出现而没有过渡。

我想在表单提交时进行转换,当我从 map() 返回数据时,有人可以告诉我如何使用 Csstransition 或 react-spring 添加此转换。

import React,{useState} from "react";
import axios from "axios";
import moment from "moment";

import { KEY } from "../../const";
import { cloudy,hurricane,rain,sNow,sunny } from "./weatherType";

import "./winderCondition.scss";
import "./weather.scss";
import {Csstransition} from "react-transition-group";

export const Weather = () => {
  const [currentWeatherData,setCurrentWeatherData] = useState([]);
  const [foreCast,setForeCast] = useState([]);
  const [query,setQuery] = useState("");

  const getCurrentWeather = async (query: string) => {
    const response = await axios.get(`https://api.weatherbit.io/v2.0/current?&city=${query ? query : ""}&key=${KEY}`)
    setCurrentWeatherData(response.data.data)
  };

  const getForecast = async (query: string) => {
    const response = await axios.get(`https://api.weatherbit.io/v2.0/forecast/daily?&city=${query ? query : ""}&key=${KEY}&days=5`)
    setForeCast(response.data.data);
    foreCast.shift();
  };

  const handleCityChange = (e: any) => {
    setQuery(e.target.value);
  };

  const handleOnSubmit = async (e: any) => {
    e.preventDefault();
  await getCurrentWeather(query);
  await getForecast(query);
  };

  const getCondition = (weatherCode: number) => {
    if (weatherCode >= 200 && weatherCode <= 233) {
      return hurricane;
    }

    if (weatherCode >= 300 && weatherCode <= 522) {
      return rain;
    }

    if (weatherCode >= 600 && weatherCode <= 610) {
      return sNow;
    }

    if (weatherCode === 800) {
      return sunny;
    }

    if (weatherCode >= 801 && weatherCode <= 900) {
      return cloudy;
    }
  };

  return (
    <div className="weather">
      <form onSubmit={handleOnSubmit}>
        <div className="input_wrapper">
        <input className="city-input"
          type="text"
          onChange={(e) => handleCityChange(e)}
          value={query}
          name="city"
        />
        <label className={query.length !== 0 ? "move-up" : "city-label"} htmlFor="city">Your City</label>
        </div>
          <button type="submit">Search</button>
      </form>
        <div className="weather-wrapper">
          {currentWeatherData &&
          currentWeatherData.map((weather: any) => {
            return (
                <Csstransition classNames="my-node" key={weather.city_name} in={true} timeout={300}>
                <div className="currentWeather">
                  <div className="gradient">
                    <div className="country">
                      Location: {`${weather.city_name},${weather.country_code}`}
                    </div>
                    <div className="temperature">
                      {Math.floor(weather.temp)} °C
                    </div>
                    {getCondition(weather.weather.code)}
                    <div>{weather.weather.description}</div>
                  </div>
                </div>
            </Csstransition>
            );
          })}
          <div className="forecast-wrapper">
            {foreCast &&
            foreCast.map((weather: any) => {
              return (
                  <div className="forecast" key={weather.ts}>
                    <div className="forecast-date">
                      {moment(weather.ts * 1000).format("dddd")}
                    </div>
                    <div>{Math.round(weather.temp)} °C</div>
                    <img
                        className="forecast-icon"
                        src={`https://www.weatherbit.io/static/img/icons/${weather.weather.icon}.png`}
                        alt="weather-condition"
                    />
                  </div>
              );
            })}
          </div>
        </div>
    </div>
  );
};

CSS

  .my-node-enter {
    opacity: 0;
  }
  .my-node-enter-active {
    opacity: 1;
    transition: opacity 500ms;
  }
  .my-node-exit {
    opacity: 1;
  }
  .my-node-exit-active {
    opacity: 0;
    transition: opacity 500ms;
  }

解决方法

只需要为它添加另一个值为 true appear={true} 和 classNames 的道具。

<CSSTransition classNames="fade" key={weather.city_name} in={true} timeout={500} appear={true]>
                <div className="currentWeather">
                  <div className="gradient">
                    <div className="country">
                      Location: {`${weather.city_name},${weather.country_code}`}
                    </div>
                    <div className="temperature">
                      {Math.floor(weather.temp)} °C
                    </div>
                    {getCondition(weather.weather.code)}
                    <div>{weather.weather.description}</div>
                  </div>
                </div>
            </CSSTransition>

  .fade-appear {
    opacity: 0.01;
  }

  .fade-appear.fade-appear-active {
    opacity: 1;
    transition: opacity 500ms ease-in;
  }
感谢用户 "wherewereat" from reddit