State Management In A Weather App using GatsbyJS, TypeScript, Recoil and React!

08-Apr-2024



weather app tutorial

Introduction

In the previous article we looked at using coordingates to get weather data.

This post looks at the state which is used to store the retrieved data. Buckle up. This is going to be a bumpy ride.

src/content-apps/weather/constants/index.ts

const OPENSTREETMAP_REVERSE_API_URI =
  'https://nominatim.openstreetmap.org/reverse';
const TOMORROWIO_API_URI = 'https://api.tomorrow.io/v4/weather/forecast';
const TIME_OF_DAY_IS_DAY_TIME = 'day';
const TIME_OF_DAY_IS_NIGHT_TIME = 'night';
const UNITS_OF_MEASUREMENT_IMPERIAL = 'imperial';
const UNITS_OF_MEASUREMENT_METRIC = 'metric';

export {
  OPENSTREETMAP_REVERSE_API_URI,
  TOMORROWIO_API_URI,
  TIME_OF_DAY_IS_DAY_TIME,
  TIME_OF_DAY_IS_NIGHT_TIME,
  UNITS_OF_MEASUREMENT_IMPERIAL,
  UNITS_OF_MEASUREMENT_METRIC,
};

About Constants

The constants file is a set of values that do not change that may be used in various places around an app - or - may be useful to keep with other values that do not change. Sometimes having a library of things is better than putting things in the only place they might be used. One has a big list of things. But you know where they are at least. The other is you have lots of things. But where did you put the thing that you need ritht now?

src/content-apps/weather/state/default-weather-location-top-card-states.ts

import { UNITS_OF_MEASUREMENT_METRIC } from '../constants';

const stateWeatherLocationTopCard = {
  location: {
    countryCode: '',
    date: '',
    licence: '',
    place: '',
  },
  weather: {
    code: 0,
    daylight: true,
    humidity: 0,
    imperial: {
      dewpoint: 0,
      temperature: {
        avg: 0,
        max: 0,
        min: 0,
        now: 0,
      },
      temperatureApparent: {
        avg: 0,
        max: 0,
        min: 0,
        now: 0,
      },
      windGust: {
        unit: 'kph',
        value: 0,
      },
      windSpeed: {
        unit: 'kph',
        value: 0,
      },
    },
    metric: {
      dewpoint: 0,
      temperature: {
        avg: 0,
        max: 0,
        min: 0,
        now: 0,
      },
      temperatureApparent: {
        avg: 0,
        max: 0,
        min: 0,
        now: 0,
      },
      windGust: {
        unit: 'm/s',
        value: 0,
      },
      windSpeed: {
        unit: 'm/s',
        value: 0,
      },
    },
    moonriseTime: '',
    moonsetTime: '',
    sunriseTime: '',
    sunsetTime: '',
    uv: {
      index: 0,
      min: 0,
      max: 0,
    },
    uvHealthConcern: {
      index: 0,
      min: 0,
      max: 0,
    },
    windDirection: 0,
  },
  units: UNITS_OF_MEASUREMENT_METRIC,
};

export { stateWeatherLocationTopCard };

About Weather Location Top Card State

The idea of the this object is to provide place for the api data to be dropped into. It has no other purpose but to house api data. The shape is more or less determined by the api data. You need to read the api documentation (of whatever api it is you are using) - or - you need to acquire data from the api - in order to build the shape of the object.

src/content-apps/weather/state/atoms.ts

import { atom } from 'recoil';
//  default states
import { stateWeatherLocationTopCard } from './default-weather-location-top-card-state';

export const weatherLocationLocale = atom({
  key: 'weatherLocationLocale',
  default: { data: {}, loaded: false, loading: false },
});

export const weatherLocationForecast = atom({
  key: 'weatherLocationForecast',
  default: { data: {}, loaded: false, loading: false },
});

export const weatherLocationTopCard = atom({
  key: 'weatherLocationTopCard',
  default: stateWeatherLocationTopCard,
});

About Atoms

First the default weather location top card state is imported because it will be used in one of the atoms.

Because we are using Recoil , the atom shapes follow the pattern described in that documentation.

As you can see the default for both weatherLocationLocale and weatherLocationForecast is simply an empty object ( or {}).

The weatherLocationTopCard is using the stateWeatherLocationTopCard state import.

What Now?

Ah, you will have to wait for the next exciting installment dear coder.

Thank you for reading thus far.

Happy coding and creating! 🌦️⚛️

#GatsbyJS #TypeScript #ReactJS #ReactQuery #Recoil #ChakraUI #WeatherApp #FrontendDev #WebDev #CodingTips

Photo by Bjark on Unsplash


Get Cool Swag

If you are finding this content useful (or maybe you are just a nice person or maybe you just like my merch) I would be greatful if you headed over to my shop and make a purchase or two. All proceeds will go towards making more courses.

If there’s merch missing that you would like, let me know (click this: Make Something For Me ) and I’ll try to make it for you.

Doom Scroller T-Shirt

Doom Scroller T-Shirt

You can buy this product or you can check out my shop of products.