У меня возникли проблемы с тем, как я должен получать данные с помощью вызова API. Я использую useQuery и искал, как его реализовать, и просто получаю ошибки с ним и асинхронные ключевые слова, которые могут или не могут быть необходимы в файле. Меня просто смущает использование клиента и то, что должно и не должно быть в таком файле.
Вот как я настроил useQuery
"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>
)
}
Вот где у меня есть 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;
}
Я думаю, что в приведенном выше коде может быть что-то, вызывающее ошибку. Возможно, usePathname и searchParams, но я не совсем уверен, как мне это решить.
также вот домашняя страница, где я использую 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>
);
}
Home определенно хорошо, потому что там я рендерю компонент. Я что-то изменил и смог отобразить console.info в Temps, но нет data. lat и lon точно передаются, поскольку я могу отображать их на консоли. Ничего, когда дело касается любых переменных, связанных с вызовом API. data и response я имею в виду
Посмотрите, сможете ли вы создать работающую демо-версию codeandbox, воспроизводящую возникшую у вас проблему, которую мы могли бы проверить в реальном времени.
Ничего, если единственные ошибки, которые я получаю, связаны только с песочницей? У меня console.infos в fetchData отображается правильно. Не знаю, как можно поделиться ссылкой. Слишком длинное
Вам нужно будет указать только URL-адрес до параметров поиска, например. что-то вроде "https://codesandbox.io/s/some-funny-name123". Убедитесь, что вы (а) добавили и сохранили все файлы и (б) пометили песочницу как общедоступную, чтобы она была доступна.
Хорошо, тогда все должно быть хорошо, чтобы идти сюда. Вот ссылка на песочницу: codeandbox.io/p/github/MarcoAntonioMartinez/nextjs-weather-app/current-version.
Хорошо, похоже, ваша песочница доступна и работает. Можете ли вы напомнить мне, какая проблема осталась и каковы конкретные шаги по воспроизведению?
Данные не отображаются. Я предполагаю, что вызов API по какой-то причине никогда не вызывается. response и data почему-то нельзя console.info. Переменная, которая должна отображать эти данные в Temps, не выдает ошибку, когда я пытаюсь получить доступ к ее свойствам, которые будут из json, возвращаемого API. Другими словами, я могу это сделать data.data.main.temps и это нормально. Так что, возможно, API вызывается, но по какой-то причине он не может отображаться должным образом.
Вся моя идея использования useQuery заключается в том, чтобы не использовать useEffect. Я мало что знаю о useState, но, возможно, мне нужно как-то обновить состояние переменных, но я решил, что useQuery уже с этим справится
Песочница доступна, и страница в конечном итоге загружается, но остается пустой. Каковы действия по воспроизведению проблемы, которая у вас все еще существует?
Введите широту и долготу в первое и второе поля ввода. В консоли будет отображаться широта, но HTML в файле Temp вообще нигде не отображается.
У вас довольно много проблем между компонентами пользовательского интерфейса и функцией выборки, что делает это более сложным, чем должно быть. Мне удалось вызвать выборку, закомментировав console.info("fetchData", data.data) в fetchData и подставив свой собственный ключ API в URL-адрес запроса. Извлечение не удается, потому что вы используете протокол http вместо https, и как только вы переключите вызовы API, они будут успешными.
Вау, это странно. Я понятия не имел, что из-за console.info он не работает в сочетании с https. Кроме того, что именно вы подразумеваете под словом crud? Я все еще новичок в nextjs и реагирую, поэтому буду рад любым отзывам. И что мне вообще делать с ответом на этот вопрос здесь? Должен ли я просто пометить ваш первоначальный ответ как ответ и оставить все как есть? Проголосовать за все комментарии, которые способствовали ответу?
Кроме того, единственная проблема, с которой я сейчас сталкиваюсь, — это получение данных для отображения в Temps. Это не сработает, если я попробую поставить Temps рядом с WeatherApp в Home и попробую поставить Temps в WeatherApp и то же самое
Извините, под «crud» я имел в виду все журналирование консоли, условия, обертывающие условные рендеры и т. д.... это было очень сложно сделать, и в конечном итоге я просто закомментировал все это и отрендерил Temps прямо в WeatherApp, чтобы увидеть, где это было. взлом вашего крючка запроса. Что касается console.info("fetchData", data.data), я подозреваю, что это связано с тем, что data не определен, поэтому доступ к data.data, скорее всего, вызывал ошибку, но перехватчик запроса молча перехватывал ее и не вызывал API. Я могу обновить свой ответ, включив в него дополнительную информацию/исправления.





Вы не можете вызвать хук React во вложенном обратном вызове, т. е. вызов usePathname в getData недействителен.
Вы можете вызвать usePathname в компоненте Temps и передать значения lat и lon в функцию запроса.
Основной пример:
"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 });
}
API OpenWeatherMap ожидают, что вы будете использовать безопасный протокол https, URL-адрес запроса должен быть:
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${process.env.NEXT_PUBLIC_API_KEY}&units=imperial`
Служебная функция fetchData неправильно зарегистрировала в консоли свойство неопределенного объекта, вероятно, вызвав исключение, которое автоматически перехватывалось хуком useQuery.
export default function fetchData({ lat, lon }){
// only lat lon log displays
console.info("fetchData lat and lon " + lat + ", " + lon); // OK
// console.info("fetchData", data.data) // Not OK, data is undefined, data.data throws
return getData({ lat, lon });
}
Конечная точка возвращает данные, подобные следующим:
{
"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
}
Это значение data, возвращаемое хуком useQuery, который Temps может использовать. Выберите из этого объекта то, что вам нужно, например. data?.main.temp это 81.95.
Мне удалось обнаружить перехваты, не поддерживаемые внутри асинхронного компонента. Ошибка возникла из-за того, что функция использовала перехваты как асинхронные в другом файле.
Теперь моя единственная проблема — отображение данных. Широта и долгота передаются, но данные не отображаются по какой-то причине, которую я не понимаю. У меня тоже был queryClient, и я не уверен, помогает ли он отображать данные или нет. Буду признателен за помощь в этом
@MarcoAntonioMartinez Вы имеете в виду data, возвращаемый useQuery хуком? Возвращаются ли из запроса правильные ожидаемые данные? Что такое значение data и как вы пытаетесь сделать его другим, просто вызывая метод .toString ссылочного объекта?
Да, я имею в виду данные, возвращаемые из перехватчика useQuery. Вообще ничего не отображается. Предполагается, что я ввожу широту и долготу, вызывается API и возвращает данные, вызывается useQuery, получает эти данные и имеет тот HTML-код, который он должен отображать, который должен отображаться только после отправки ввода. Данные, которые я пытаюсь отобразить, просто чтобы проверить, работают ли они, поскольку data.toString не работает, — это data.data.main.temps, которые я получил из json для Openweather. Я имею в виду JSON, который должен быть возвращен при звонке
@MarcoAntonioMartinez Какова стоимость response от const response = await fetch(...)... или стоимость data от const data = await getData(); или стоимость data от const { data, error, isError } = useQuery({....})?
Когда я говорю, что должно отображаться только при отправке ввода, у меня есть переменная, для которой установлено значение true при отправке формы. Там, где я размещаю компонент, он выглядит следующим образом: {isSubmited && <Temps />}
Я не могу сказать. Я пытаюсь использовать console.info, но ничего не отображается. Я помещаю это в функцию getData, добавляю fetchData и ничего
Хорошо, я ценю всю помощь, которую вы мне оказали в этом проекте. У меня возникла небольшая проблема. Я думал, что не смогу заставить ее работать, но это произошло потому, что у меня она была типа data?.main.temps, и приложение какое-то время ничего с этим не делало. Возможно было что-то еще, но в любом случае сейчас все работает как надо. Еще раз спасибо за вашу помощь. Я был бы признателен за любые советы, которые вы могли бы дать мне, как сделать проект более профессиональным и аккуратным, если это возможно.
Если хук
useQueryи функцияfetchDataне вызываются, компонентыHomeиTempsвообще рендерятся? Кажется, вам нужно немного отладить, начиная с верхнего/корневого компонента, и двигаться вниз по ReactTree, чтобы проверить, что на самом деле смонтировано, какие перехватчики жизненного цикла вызываются и когда они вызываются, прежде чем вы сможете начать. проверка полученных значений ответа.