如何通过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
相关产品推荐
相关产品推荐

