Перехватчики не поддерживаются внутри ошибки асинхронного компонента в проекте nextjs с использованием useQuery

У меня возникли проблемы с тем, как я должен получать данные с помощью вызова 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>
  );
}

Если хук useQuery и функция fetchData не вызываются, компоненты Home и Temps вообще рендерятся? Кажется, вам нужно немного отладить, начиная с верхнего/корневого компонента, и двигаться вниз по ReactTree, чтобы проверить, что на самом деле смонтировано, какие перехватчики жизненного цикла вызываются и когда они вызываются, прежде чем вы сможете начать. проверка полученных значений ответа.

Drew Reese 08.04.2024 01:43
Home определенно хорошо, потому что там я рендерю компонент. Я что-то изменил и смог отобразить console.info в Temps, но нет data. lat и lon точно передаются, поскольку я могу отображать их на консоли. Ничего, когда дело касается любых переменных, связанных с вызовом API. data и response я имею в виду
Marco Antonio Martinez 13.04.2024 00:57

Посмотрите, сможете ли вы создать работающую демо-версию codeandbox, воспроизводящую возникшую у вас проблему, которую мы могли бы проверить в реальном времени.

Drew Reese 13.04.2024 01:18

Ничего, если единственные ошибки, которые я получаю, связаны только с песочницей? У меня console.infos в fetchData отображается правильно. Не знаю, как можно поделиться ссылкой. Слишком длинное

Marco Antonio Martinez 13.04.2024 20:26

Вам нужно будет указать только URL-адрес до параметров поиска, например. что-то вроде "https://codesandbox.io/s/some-funny-name123". Убедитесь, что вы (а) добавили и сохранили все файлы и (б) пометили песочницу как общедоступную, чтобы она была доступна.

Drew Reese 14.04.2024 00:32

Хорошо, тогда все должно быть хорошо, чтобы идти сюда. Вот ссылка на песочницу: codeandbox.io/p/github/MarcoAntonioMartinez/nextjs-weather-‌​app/current-version.

Marco Antonio Martinez 15.04.2024 20:42

Хорошо, похоже, ваша песочница доступна и работает. Можете ли вы напомнить мне, какая проблема осталась и каковы конкретные шаги по воспроизведению?

Drew Reese 15.04.2024 20:46

Данные не отображаются. Я предполагаю, что вызов API по какой-то причине никогда не вызывается. response и data почему-то нельзя console.info. Переменная, которая должна отображать эти данные в Temps, не выдает ошибку, когда я пытаюсь получить доступ к ее свойствам, которые будут из json, возвращаемого API. Другими словами, я могу это сделать data.data.main.temps и это нормально. Так что, возможно, API вызывается, но по какой-то причине он не может отображаться должным образом.

Marco Antonio Martinez 16.04.2024 20:37

Вся моя идея использования useQuery заключается в том, чтобы не использовать useEffect. Я мало что знаю о useState, но, возможно, мне нужно как-то обновить состояние переменных, но я решил, что useQuery уже с этим справится

Marco Antonio Martinez 16.04.2024 20:37

Песочница доступна, и страница в конечном итоге загружается, но остается пустой. Каковы действия по воспроизведению проблемы, которая у вас все еще существует?

Drew Reese 19.04.2024 18:44

Введите широту и долготу в первое и второе поля ввода. В консоли будет отображаться широта, но HTML в файле Temp вообще нигде не отображается.

Marco Antonio Martinez 19.04.2024 23:24

У вас довольно много проблем между компонентами пользовательского интерфейса и функцией выборки, что делает это более сложным, чем должно быть. Мне удалось вызвать выборку, закомментировав console.info("fetchData", data.data) в fetchData и подставив свой собственный ключ API в URL-адрес запроса. Извлечение не удается, потому что вы используете протокол http вместо https, и как только вы переключите вызовы API, они будут успешными.

Drew Reese 20.04.2024 00:18

Вау, это странно. Я понятия не имел, что из-за console.info он не работает в сочетании с https. Кроме того, что именно вы подразумеваете под словом crud? Я все еще новичок в nextjs и реагирую, поэтому буду рад любым отзывам. И что мне вообще делать с ответом на этот вопрос здесь? Должен ли я просто пометить ваш первоначальный ответ как ответ и оставить все как есть? Проголосовать за все комментарии, которые способствовали ответу?

Marco Antonio Martinez 20.04.2024 04:16

Кроме того, единственная проблема, с которой я сейчас сталкиваюсь, — это получение данных для отображения в Temps. Это не сработает, если я попробую поставить Temps рядом с WeatherApp в Home и попробую поставить Temps в WeatherApp и то же самое

Marco Antonio Martinez 20.04.2024 04:35

Извините, под «crud» я имел в виду все журналирование консоли, условия, обертывающие условные рендеры и т. д.... это было очень сложно сделать, и в конечном итоге я просто закомментировал все это и отрендерил Temps прямо в WeatherApp, чтобы увидеть, где это было. взлом вашего крючка запроса. Что касается console.info("fetchData", data.data), я подозреваю, что это связано с тем, что data не определен, поэтому доступ к data.data, скорее всего, вызывал ошибку, но перехватчик запроса молча перехватывал ее и не вызывал API. Я могу обновить свой ответ, включив в него дополнительную информацию/исправления.

Drew Reese 20.04.2024 07:11
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
15
187
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете вызвать хук 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 });
}

Дополнительные проблемы, решаемые в коде песочницы

  1. 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`
    
  2. Служебная функция 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 });
    }
    
  3. Конечная точка возвращает данные, подобные следующим:

    {
        "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.

Мне удалось обнаружить перехваты, не поддерживаемые внутри асинхронного компонента. Ошибка возникла из-за того, что функция использовала перехваты как асинхронные в другом файле.

Marco Antonio Martinez 06.04.2024 03:47

Теперь моя единственная проблема — отображение данных. Широта и долгота передаются, но данные не отображаются по какой-то причине, которую я не понимаю. У меня тоже был queryClient, и я не уверен, помогает ли он отображать данные или нет. Буду признателен за помощь в этом

Marco Antonio Martinez 06.04.2024 03:55

@MarcoAntonioMartinez Вы имеете в виду data, возвращаемый useQuery хуком? Возвращаются ли из запроса правильные ожидаемые данные? Что такое значение data и как вы пытаетесь сделать его другим, просто вызывая метод .toString ссылочного объекта?

Drew Reese 06.04.2024 04:37

Да, я имею в виду данные, возвращаемые из перехватчика useQuery. Вообще ничего не отображается. Предполагается, что я ввожу широту и долготу, вызывается API и возвращает данные, вызывается useQuery, получает эти данные и имеет тот HTML-код, который он должен отображать, который должен отображаться только после отправки ввода. Данные, которые я пытаюсь отобразить, просто чтобы проверить, работают ли они, поскольку data.toString не работает, — это data.data.main.temps, которые я получил из json для Openweather. Я имею в виду JSON, который должен быть возвращен при звонке

Marco Antonio Martinez 07.04.2024 23:48

@MarcoAntonioMartinez Какова стоимость response от const response = await fetch(...)... или стоимость data от const data = await getData(); или стоимость data от const { data, error, isError } = useQuery({....})?

Drew Reese 07.04.2024 23:56

Когда я говорю, что должно отображаться только при отправке ввода, у меня есть переменная, для которой установлено значение true при отправке формы. Там, где я размещаю компонент, он выглядит следующим образом: {isSubmited && <Temps />}

Marco Antonio Martinez 07.04.2024 23:58

Я не могу сказать. Я пытаюсь использовать console.info, но ничего не отображается. Я помещаю это в функцию getData, добавляю fetchData и ничего

Marco Antonio Martinez 08.04.2024 00:27

Хорошо, я ценю всю помощь, которую вы мне оказали в этом проекте. У меня возникла небольшая проблема. Я думал, что не смогу заставить ее работать, но это произошло потому, что у меня она была типа data?.main.temps, и приложение какое-то время ничего с этим не делало. Возможно было что-то еще, но в любом случае сейчас все работает как надо. Еще раз спасибо за вашу помощь. Я был бы признателен за любые советы, которые вы могли бы дать мне, как сделать проект более профессиональным и аккуратным, если это возможно.

Marco Antonio Martinez 20.04.2024 21:33

Другие вопросы по теме

Создание пользовательских кнопок истории назад и вперед с помощью перехватчика React
Получение React Hook «useSetupInterceptors» не может быть вызвано на верхнем уровне при попытке использовать перехват useSignOut
Текст пользовательской кнопки экспорта становится неопределенным при использовании useEffect в Canvasjs
Правильно ли использовать подписку в useEffect?
Маршрутизация страниц Typescript не отображает подстраницу при нажатии (React Router v6)
Ошибка типа: невозможно прочитать свойства неопределенного значения (чтение «карты») в реакции разработки
Предупреждения о машинописных текстах, исчерпывающие-deps, список зависимостей useEffect
Проблема со страницей Next.js, отображающей неправильные данные при быстрой навигации между страницами
Как сохранить смонтированный iframe в React после размонтирования его родительского элемента
React.js – дождитесь обновления состояния