I've been having trouble with how I'm supposed to fetch the data using an API call. I'm using useQuery and I've looked around for how I'm supposed to implement it and I'm just getting errors with it and async keywords that may or may not be needed in the file. I'm just confused with use client and what should and shouldn't be in that kind of file.
Here's how I have useQuery set up
"use client"
import { useQuery } from "@tanstack/react-query";
import fetchData from "../app/fetchData.jsx";
export default function Temps(){
const{ data, error, isError } = useQuery({
queryKey: ["wdata"],
queryFn: () => fetchData(),
});
if (isError) <span>Error: {error.message}</span>
if(data)
return(
<div>
<p> {data.toString()}</p>
</div>
)
}
Here's where I have fetchData
"use client"
import { usePathname } from "next/navigation";
async function getData(){
const options = {
method:"GET",
headers: {
accept: "application/json",
},
};
const pathName = usePathname();
const { searchParams } = pathName;
const lat = searchParams.get('lat');
const lon = searchParams.get('lon');
const response = await fetch(
`http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${process.env.API_KEY}&units=imperial`,
options)
.then ((response) => response.json())
.catch((err) => console.error(err));
return response;
}
export default async function fetchData(){
const data = await getData();
return data;
}
I'm thinking there might be something in the above code that's causing the error. Maybe the usePathname and searchParams but I'm not exactly sure how I should solve it.
also here's the home page where I use useQueryClient
import WeatherApp from './WeatherApp';
import { QueryClient } from '@tanstack/react-query';
import fetchData from './fetchData';
import Temps from '@/components/Temps';
export default async function Home() {
const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryKey: ["wdata"],
queryFn: () => fetchData(),
})
return (
<div>
<WeatherApp />
<Temps />
</div>
);
}
You can't call a React hook in a nested callback, i.e. calling usePathname
in getData
is not valid.
You can call usePathname
in the Temps
component and pass the lat
, and lon
values to the query function.
Basic Example:
"use client"
import { useQuery } from "@tanstack/react-query";
import { usePathname } from "next/navigation";
import fetchData from "../app/fetchData.jsx";
export default function Temps() {
const { searchParams } = usePathname();
const lat = searchParams.get('lat');
const lon = searchParams.get('lon');
const { data, error, isError } = useQuery({
queryKey: ["wdata", lat, lon],
queryFn: () => fetchData({ lat, lon }),
});
if (isError) <span>Error: {error.message}</span>;
if (data)
return (
<div>
<p>{JSON.stringify(data)}</p>
</div>
);
}
}
"use client"
import { usePathname } from "next/navigation";
async function getData({ lat, lon }) {
const options = {
method:"GET",
headers: {
accept: "application/json",
},
};
try {
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${process.env.API_KEY}&units=imperial`,
options
)
const data = await response.json();
return data;
} catch(err) {
console.error(err);
throw err; // re-throw for query
};
}
export default function fetchData({ lat, lon }) {
return getData({ lat, lon });
}
The OpenWeatherMap APIs expect you to use the secure https
protocol, the request URL should be:
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${process.env.NEXT_PUBLIC_API_KEY}&units=imperial`
The fetchData
utility function incorrectly console logged a property of an undefined object, likely throwing an exception that was being silently caught by the useQuery
hook.
export default function fetchData({ lat, lon }){
// only lat lon log displays
console.log("fetchData lat and lon " + lat + ", " + lon); // OK
// console.log("fetchData", data.data) // Not OK, data is undefined, data.data throws
return getData({ lat, lon });
}
The endpoint returns data similar to the following:
{
"coord": {
"lon": 43,
"lat": 23
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"base": "stations",
"main": {
"temp": 81.95,
"feels_like": 79.79,
"temp_min": 81.95,
"temp_max": 81.95,
"pressure": 1009,
"humidity": 19,
"sea_level": 1009,
"grnd_level": 898
},
"visibility": 10000,
"wind": {
"speed": 3.53,
"deg": 307,
"gust": 5.82
},
"clouds": {
"all": 1
},
"dt": 1713591517,
"sys": {
"country": "SA",
"sunrise": 1713580975,
"sunset": 1713627024
},
"timezone": 10800,
"id": 110250,
"name": "Afif",
"cod": 200
}
This is the data
value returned by the useQuery
hook that Temps
can use. Select what you need from this object, e.g. data?.main.temp
is 81.95
.