有没有办法动态改变react-query查询?

问题描述 投票:0回答:1

我有一个带有react-query的next.js项目。基本上我需要做的是在主页上显示 API 中的所有国家/地区,但还有一个按名称搜索的输入,以及一个按区域搜索的选择。我如何更改基于此调用的查询?

我想过将数据保存到 useState 然后显示它,但这似乎浪费了反应查询的潜力。这是我组织代码的方式:

国家.service.ts

import { Regions } from '@/queries/types';
import axios from 'axios';

export class CountriesService {
  static client = axios.create({
    baseURL: `${process.env.NEXT_PUBLIC_API_URL}`,
  });

  static async getAllCountries() {
    const response = await CountriesService.client.get('/all');

    return response.data;
  }

  static async getCountryByName(name: string) {
    const response = await CountriesService.client.get(`/name/${name}`);

    return response.data;
  }

  static async getCountryByRegion(region: Regions) {
    const response = await CountriesService.client.get(`/region/${region}`);

    return response.data;
  }
}

国家.query.ts

import { useQuery } from '@tanstack/react-query';

import { CountriesService } from '@/services/countries.service';
import { Regions } from './types';

export class CountriesQuery {
  static getAllCountries() {
    return useQuery({
      queryKey: ['get-all-countries'],
      queryFn: async () => {
        const data = await CountriesService.getAllCountries();

        return data;
      },
    });
  }

  static getCountryByName({ name }: { name: string }) {
    return useQuery({
      queryKey: ['get-country-by-name'],
      queryFn: async () => {        
        const data = await CountriesService.getCountryByName(name);

        return data;
      },
    });
  }

  static getCountryByRegion({ region }: { region: Regions }) {
    return useQuery({
      queryKey: ['get-country-by-region'],
      queryFn: async () => {        
        const data = await CountriesService.getCountryByName(region);

        return data;
      },
    });
  }
}

页面.tsx

'use client';

import { CountryCard } from "@/components/country-card";
import { CountriesQuery } from "@/queries/countries.query";
import { Country } from "@/queries/types";
import { MagnifyingGlass } from "@phosphor-icons/react";
import { useState } from "react";

export default function Home() {
  const [searchName, setSearchName] = useState('');

  const { data, isLoading} = CountriesQuery.getAllCountries();

  const handleSearchByName = async (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchName(e.target.value);
  };

  if (isLoading) {
    //make skeleton
    return;
  };

  return (
    <main>
      <div>
        <input onChange={handleSearchByName} placeholder="Search for a country..." />
        <button><MagnifyingGlass weight="bold" /></button>
      </div>
      <div>
        {data.map((country: Country) => (
          <div key={country.name.common} >
            <CountryCard
              flagSrc={country.flags.png}
              name={country.name.common}
              population={country.population}
              region={country.region}
              capital={country.capital}
            />
          </div>
        ))}
      </div>
    </main>
  )
}
reactjs next.js axios react-query tanstackreact-query
1个回答
0
投票

您过度指定了自定义查询挂钩(并且还违反了挂钩规则)。

将其实现为自定义挂钩的正确方法如下:

export const useCountryQuery({ name, region, ...options } = {}) {
  return useQuery({
    queryKey: ['get-country', {name, region}]}
    queryFn: () => {
        if(name) {
          return CountriesService.getCountryByName(name);
        }
        if(region) {
          return CountriesService.getCountryByRegion(region);
        }
        return CountriesService.getAllCountries();
    },
    ...options
  })
}

用法如下:

const [searchName, setSearchName] = useState('');

const { data, isLoading } = useCountryQuery({name: searchName});

const handleSearchByName = async (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchName(e.target.value);
};
// ...
© www.soinside.com 2019 - 2024. All rights reserved.