Use Coordinates To Get The Location Name In A Weather App with GatsbyJS, TypeScript, Recoil and React!

12-Feb-2024



weather app tutorial

Introduction

In the previous article we looked at passing coordingates into a couple of “dumb components”. What these components really do we will look at in a bit more detail here.

This post details the hook used in the src/content-apps/weather/data/utilize-coordinates-locale.tsx file.

src/content-apps/weather/hooks/use-location-name-query-by-coords.ts

import { useEffect } from 'react';
//  react-query
import { useQuery } from '@tanstack/react-query';
//  recoil
import { useSetRecoilState } from 'recoil';
//  helpers
import getLocationByCoordinatesUri from '../helpers/get-location-by-coordinates-uri';
import setTopCardLocale from '../helpers/set-recoil-state-top-card-locale';
//  recoil
import { weatherLocationLocale, weatherLocationTopCard } from '../state/atoms';
//  types
import { Coordinates } from '../types';

interface Payload extends Coordinates {
  dev?: boolean;
}

const useLocationNameQuery = (payload: Payload) => {
  const { latitude, longitude } = payload;
  const { data, error, isPending } = useQuery({
    queryKey: ['weather-location-name'],
    queryFn: () =>
      fetch(
        getLocationByCoordinatesUri({
          latitude,
          longitude,
        }),
      )
        .then((res) => {
          if (res) {
            if (res.status !== 200) {
              throw new Error(JSON.stringify(res.statusText));
            }
          }

          return res;
        })
        .then(async (res) => {
          const result = await res.json();

          return result;
        }),
  });
  const setLocale = useSetRecoilState(weatherLocationLocale);
  const setTopCardLocaleRecoil = useSetRecoilState(weatherLocationTopCard);

  //  error effect
  useEffect(() => {
    if (error) {
      const errorData = {
        error: true,
        message: `An error has occurred: ${error.message}`,
      };

      setLocale({ data: errorData, loaded: true, loading: false });
    }
  }, [error]);

  //  data effect
  useEffect(() => {
    if (!error && !isPending && data) {
      setLocale({
        data: { ...data, error: false },
        loaded: true,
        loading: false,
      });
      setTopCardLocale({ data, setState: setTopCardLocaleRecoil });
    }
  }, [error, isPending, data]);

  //  isPending effect
  useEffect(() => {
    if (isPending) {
      setLocale({ data: { error: false }, loaded: false, loading: true });
    }
  }, [isPending]);

  return null;
};

export default useLocationNameQuery;

Imports

Make sure you have installed @tanstack/react-query . You will need it.

This hook uses react-query’s useQuery hook. You will also notice it uses useSetRecoilState from recoil, and useEffect from React, a couple of helpers, and a couple of atoms (for using with recoil state manager). Plus some types I have defined (the Payload extends the Coordinates type). Oh, it appears dev?: boolean; is superfluous. My bad.

Payload

The hook itself expects latitude and longitude to be passed into it via the payload.

Variables

Next the hook defines the useQuery, which uses fetch to return data from a URI provided by a helper (getLocationByCoordinatesUri). The fetch query is set up to ensure if an error occurs, something icky happens, but not too icky. Otherwise, it simply awaits the data which we hope to retrieve from the URI.

After that we define our setStates of recoil (setLocale and setTopCardLocaleRecoil).

Effects

Now we can start defining our useEffects. I like to put them in alphabetical order by basic action. In this case error handling comes first.

The error effect simply responds to the error provided (maybe) by the useQuery error. Should an error occur, the setLocale state is set accordingly. You can see that an object is set, with data set with errorData, and loaded set to true and loading set to false. I like to be verbose with loaded and loading. I could just use loaded being true or false but I find I do not get the granular control I like to have most times when working with APIs.

The next effect uses relies on error, isPending and data from useQuery to respond to. Within it, assuming certain conditions are met, setLocale and setTopCardLocale are given data.

The last effect uses isPending to respond to which comes from useQuery. If the data isPending, I set the setLocale state with loaded and and loading flags appropriately, and set data a little bit.

Return

Because this code feeds recoil states, I do not bother to return anything but null from this hook. Recoil states are available anywhere I have made recoil available in my system.

Cool.

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.

The System Is Fixed T-Shirt

The System Is Fixed T-Shirt

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