You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过react-query让独立行星列表组件随搜索结果重渲染?

解决方案

当然可行,核心是让两个组件共享搜索关键词状态,并让PlanetsList基于这个关键词获取对应的数据。下面是两种常用实现方式:

方式一:状态提升到共同父组件(最直接)

把搜索关键词的状态放到两个组件的共同父组件中,通过props传递给子组件,实现状态共享:

1. 父组件维护搜索状态

import { useState } from 'react';
import SearchBox from './SearchBox';
import PlanetsList from './PlanetsList';

const ParentComponent = () => {
  const [searchTerm, setSearchTerm] = useState('');

  return (
    <div>
      <SearchBox searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
      <PlanetsList searchTerm={searchTerm} />
    </div>
  );
};

2. 修改SearchBox组件(只负责更新搜索词)

const SearchBox = ({ searchTerm, setSearchTerm }) => {
  const handleInputChange = (e) => {
    setSearchTerm(e.target.value.trim());
  };

  return (
    <input
      type="text"
      value={searchTerm}
      onChange={handleInputChange}
      placeholder="搜索星球..."
    />
  );
};

3. 修改PlanetsList组件(根据搜索词获取数据)

import { useQuery } from 'react-query';

const PlanetsList = ({ searchTerm }) => {
  // 基于搜索词生成唯一查询key,React Query会自动管理缓存和重新请求
  const { data, status } = useQuery(
    ['planets', searchTerm],
    () => {
      // 根据是否有搜索词,调用不同的接口函数
      return searchTerm 
        ? fetchSearchingResults('planets', searchTerm) 
        : fetchResourceData('planets');
    },
    { enabled: true } // 始终启用查询,空搜索词时获取全部数据
  );

  // 渲染逻辑:根据status和data展示内容
  if (status === 'loading') return <div>加载中...</div>;
  if (status === 'error') return <div>加载失败</div>;

  return (
    <ul>
      {data?.map(planet => (
        <li key={planet.id}>{planet.name}</li>
      ))}
    </ul>
  );
};

方式二:使用React Context(适合深层组件嵌套)

如果两个组件层级较深,props传递麻烦,可以用Context共享搜索状态:

1. 创建搜索Context

import { createContext, useContext, useState } from 'react';

const SearchContext = createContext({
  searchTerm: '',
  setSearchTerm: () => {},
});

export const SearchProvider = ({ children }) => {
  const [searchTerm, setSearchTerm] = useState('');
  return (
    <SearchContext.Provider value={{ searchTerm, setSearchTerm }}>
      {children}
    </SearchContext.Provider>
  );
};

export const useSearch = () => useContext(SearchContext);

2. 用Provider包裹组件

import { SearchProvider } from './SearchContext';
import SearchBox from './SearchBox';
import PlanetsList from './PlanetsList';

function App() {
  return (
    <SearchProvider>
      <SearchBox />
      <PlanetsList />
    </SearchProvider>
  );
}

3. 修改SearchBox组件

import { useSearch } from './SearchContext';

const SearchBox = () => {
  const { searchTerm, setSearchTerm } = useSearch();

  const handleInputChange = (e) => {
    setSearchTerm(e.target.value.trim());
  };

  return (
    <input
      type="text"
      value={searchTerm}
      onChange={handleInputChange}
      placeholder="搜索星球..."
    />
  );
};

4. 修改PlanetsList组件

import { useQuery } from 'react-query';
import { useSearch } from './SearchContext';

const PlanetsList = () => {
  const { searchTerm } = useSearch();

  const { data, status } = useQuery(
    ['planets', searchTerm],
    () => searchTerm 
      ? fetchSearchingResults('planets', searchTerm) 
      : fetchResourceData('planets'),
    { enabled: true }
  );

  // 渲染逻辑和方式一一致
};

核心原理

原来的实现中,两个组件使用了不同的React Query查询key(['planets', searchTerm] vs 'planets'),导致缓存完全隔离。通过共享搜索词,让PlanetsList使用带搜索词的查询key,React Query会自动识别key变化,重新发起请求并更新组件。

内容的提问来源于stack exchange,提问作者univerz17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 23:10:59