Custom hook: useIpLocation
I mitt senaste inlägg IP-baserad plats testade jag ett API som hämtar en användares IP-adressplats.
I det här inlägget beskriver jag hur jag gör det till en hook, så att IP-adressplatsen kan användas enkelt var som helst i en applikation.
Så här designade jag hooken:
/* eslint-disable camelcase */
import { useEffect, useState } from "react"
interface IpLocation {
ip: string
version: string
city: string
region: string
region_code: string
country: string
country_name: string
country_code: string
country_code_iso3: string
country_capital: string
country_tld: string
continent_code: string
in_eu: string
postal: string
latitude: number
longitude: number
timezone: string
utc_offset: string
country_calling_code: string
currency: string
currency_name: string
languages: string
country_area: number
country_population: number
asn: string
org: string
}
export const useIpLocation = () => {
const [ipLocation, setIpLocation] = useState<IpLocation | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState("")
useEffect(() => {
setLoading(true)
setIpLocation(null)
setError("")
fetch("https://ipapi.co/json/")
.then((res) => res.json())
.then((ipLocation: IpLocation) => {
setIpLocation(ipLocation)
})
.catch(() => {
setError("Could not get IP address information.")
})
.finally(() => {
setLoading(false)
})
}, [])
return { ipLocation, loading, error }
}
Att använda hooken är så här enkelt:
const { ipLocation, loading, error } = useIpLocation()
Det finns många anledningar till varför det är en bra idé att extrahera API-frågor till hooks. En viktig anledning är inkapsling.
useEffect är fantastisk, men den ger ingen som helst ledtråd till vad som faktiskt görs. Man behöver läsa innehållet i callbacken för att få en bild av vad som händer. En extraktion till en hook gör det möjligt att ge hooken ett bra namn som gör den lättare att förstå. I det här fallet useIpLocation.
En annan bra sak när TypeScript används är att responstypen IpLocation kan definieras i hooken som sedan härleds till där hooken används. Om API-frågan hade gjorts i useEffect i varje komponent som behöver information hade typen behövts definieras eller importeras i varje komponent.
En tredje fördel är att error- och laddningslogiken kan definieras på ett ställe och användas som önskas i stället för att behöva fundera över hur dessa saker ska definieras i varje komponent.
