DEV Community

Cover image for Ideas for a Weather App with React
Anne Quinkenstein
Anne Quinkenstein

Posted on

Ideas for a Weather App with React

WEATHER APP

WeatherappPic

If you allow to grab your Device Location or type in a City of your Choice, the WeatherApp will display the weather of today in a moving clouf & a 5-days forecast. A picture of the weather accourding to day or nighttime will appear in the background.

Demo Code

Built With

Librarys

APIs

Special Gotchas

Fetch Geolocation

Computer Question for GeoLocation

const getLocation = () => {
  navigator.geolocation.getCurrentPosition((position) => {
    const lat = position.coords.latitude;
    const lon = position.coords.longitude;
    fetchData(lat, lon);
  }, error);
};
Enter fullscreen mode Exit fullscreen mode

Fetch Weatherdata & Errorhandling

const onSearch = (cityName) => {
  fetch(
    `https://api.openweathermap.org/data/2.5/forecast?q=${cityName}&appid=${process.env.REACT_APP_OPENWEATHER_API_KEY}&units=metric`
  )
    .then((res) => {
      if (res.status === 404) {
        throw new Error("I didn't find this city. Please try again!");
      } else {
        setErr(null);
        return res.json();
      }
    })
    .then(
      (data) => setData(data),
      (err) => setErr(err)
    );
};
Enter fullscreen mode Exit fullscreen mode

Hidden Key

Key for open Weather APIs is hidden in .env file, which is part of .gitignore to avoid pushing it to github

Open API Fetch

The weather is either pulled with the latitude/ longitude or accourding to a city with is typed in.

Error-Handling

If the typed in City-name is not known by the API, it returns 404 + there will be thrown an error to inform the user.
Errormessage for wrong City

Show different Pages accourding to an event

Show either
Sucess -> if

  • Geolocation is allowed
  • Data from Open Weather API is fetched

Error -> if

  • Geolocation is not allowed

Loading -> if

  • Data is on it's way

  const renderData = () => {
    if (data) {
      return <Home {...data} onSearch={onSearch} err={err} />
    } else if (errorState) {
      return <NoLocationAllowed setErrorStateFalse={setErrorStateFalse} onSearch={onSearch} />
    } else {
      return <Loading isLoading={!data} />
    }
  }

  return (
[...]
    <div className='Maincomponent fade'>
       {renderData()}
    </div>
[...]  
  );
Enter fullscreen mode Exit fullscreen mode

Animations

Fading in Animations on changing Sites with React Transition Group

I used React Switch Transition, because i wanted to control the render between state transitions. The Current Weather Blub is animated, if the city is changing and a new Blub is displayed. The part in JSX has a key for each Weather + and a timeset which is the mirrowed in the CSS Part, where is set what is going to happen in the time-in & -out.

 <SwitchTransition>
      <CSSTransition
        key={props.city.id}
        timeout={{
            enter: 800,
            exit: 50
        }}
       classNames='currentWeather'
                    >
       <CurrentWeather {...props} />
      </CSSTransition>
 </SwitchTransition>
Enter fullscreen mode Exit fullscreen mode

There are 3 stages for Entry & Exit, which are explained here & the enter animation in CSS:

.currentWeather-enter {
  transform: scale(0.98);
  opacity: 0.5;
}
.currentWeather-enter-active {
  transform: scale(1);
  opacity: 1;
  transition: transform 0.8s cubic-bezier(0.37, 0, 0.63, 1), opacity 0.8s;
}
Enter fullscreen mode Exit fullscreen mode

Blob-Animation of Current Weather

CurrentWeahter Blob

<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<div className="pic">
...
</div>
Enter fullscreen mode Exit fullscreen mode
servral -> 
 span {
        position: absolute;
        top: 0;
        left: 0;
        background: radial-gradient(#ffffff50 90%, #ffffff);
        &:nth-child {
          border-radius: different border-radius to different childs; 
          animation: rotate animation; 
        }
      }
Enter fullscreen mode Exit fullscreen mode

Border-Animation of 5-day Forecast

5-days forecast

import emotion Libary to use CSS with Javascript

/** @jsx jsx */
import { jsx, css, keyframes } from "@emotion/core";
Enter fullscreen mode Exit fullscreen mode

use a random Number to set the borders in a time intervall

 const setrandNum = () => {
    return setInterval(
      () => setRandNumTopLeft(Math.floor(Math.random() * 40) + 50),
      16000
    );
  };

   const morph = keyframes`
    50% {
        border-radius: ${randNumTopLeft3}px ${randNumTopRight3}px ${randNumBottomLeft3}px ${randNumBottomRight3}px / ${randNumTopLeft4}px ${randNumTopRight4}px ${randNumBottomLeft4}px ${randNumBottomRight4}px;
    } .... 

     <div 
      css={css`
        animation: ${morph} 16s ease-in-out;
        animation-iteration-count: infinite;
      `}
      className="Day"
    >
Enter fullscreen mode Exit fullscreen mode

Changing Background-Pics Animations

The Open Weather App sents a Code for each Weather Conditions at Day & Night-Time. I got royalty free pics from Unsplash and Pexels. I renamed the pics like the codes and put the Codes as a variabel in the urls for the background-pic. To access the CSS i used the libary emotion + to access the body tag to change the background-pic on body i used the react-body-classname library.

/** @jsx jsx */
import BodyClassName from 'react-body-classname';
import { jsx } from '@emotion/core'

let sectionStyle = (process.env.PUBLIC_URL + `/images/${image()}.png`);

<BodyClassName className="container" css={{ backgroundImage: `url("${errorState ? errorStyle : sectionStyle}")` }}>

Enter fullscreen mode Exit fullscreen mode

Calculations

Round a num

const temp = (props.main.temp * 2).toFixed() / 2;
Rounded to .5

Contact

Don't hesitate to get in touch!

Discussion (0)