如何在Redux切片状态变化时触发RTK Query请求?
用RTK Query订阅筛选器状态变化并触发请求
核心思路
RTK Query的useQuery会自动追踪查询参数的变化,只要把Redux Store中的筛选器状态作为查询参数传入,就能在筛选条件更新时自动触发新请求。如果需要手动控制触发时机,也可以用useLazyQuery配合useEffect监听筛选器状态变化。
步骤1:创建筛选器状态切片
先定义一个Redux切片来存储筛选器状态,包含更新筛选条件的reducer:
import { createSlice } from '@reduxjs/toolkit'; const initialState = { category: '', priceRange: '', // 按需添加其他筛选字段 }; const filtersSlice = createSlice({ name: 'filters', initialState, reducers: { updateFilter: (state, action) => { const { key, value } = action.payload; state[key] = value; }, resetFilters: () => initialState, }, }); export const { updateFilter, resetFilters } = filtersSlice.actions; export default filtersSlice.reducer;
步骤2:自动触发请求(推荐方式)
使用useQuery,直接将筛选器状态作为查询参数传入。当筛选器状态变化时,RTK Query会自动对比参数差异,发起新请求:
import { useSelector, useDispatch } from 'react-redux'; import { useGetDataQuery } from './apiSlice'; // 你的RTK Query API切片 import { updateFilter } from './filtersSlice'; function DataListPage() { const dispatch = useDispatch(); // 从Redux Store获取当前筛选器状态 const filters = useSelector(state => state.filters); // 将筛选器作为查询参数,参数变化时自动重新请求 const { data, error, isLoading } = useGetDataQuery(filters); return ( <div> {/* 分类筛选下拉框 */} <select value={filters.category} onChange={(e) => { dispatch(updateFilter({ key: 'category', value: e.target.value })); }} > <option value="">所有分类</option> <option value="electronics">电子产品</option> <option value="clothing">服饰</option> </select> {/* 价格区间筛选(示例) */} <select value={filters.priceRange} onChange={(e) => { dispatch(updateFilter({ key: 'priceRange', value: e.target.value })); }} > <option value="">不限价格</option> <option value="0-100">0-100元</option> <option value="100-500">100-500元</option> </select> {/* 数据渲染 */} {isLoading && <div>加载中...</div>} {error && <div>请求失败:{error.message}</div>} {data && ( <ul> {data.map(item => ( <li key={item.id}>{item.name} - {item.price}元</li> ))} </ul> )} </div> ); } export default DataListPage;
步骤3:手动控制请求触发时机
如果需要更灵活的触发逻辑(比如点击"搜索"按钮才请求),可以用useLazyQuery配合useEffect监听筛选器变化:
import { useSelector, useDispatch } from 'react-redux'; import { useLazyGetDataQuery } from './apiSlice'; import { updateFilter } from './filtersSlice'; import { useEffect } from 'react'; function DataListPage() { const dispatch = useDispatch(); const filters = useSelector(state => state.filters); // 初始化lazy query,返回触发函数和请求状态 const [triggerGetData, { data, error, isLoading }] = useLazyGetDataQuery(); // 监听筛选器变化,自动触发请求 useEffect(() => { triggerGetData(filters); }, [filters, triggerGetData]); // 或者添加按钮手动触发 const handleSearch = () => { triggerGetData(filters); }; return ( <div> {/* 筛选器组件 */} <button onClick={handleSearch}>搜索</button> {/* 数据渲染 */} </div> ); }
优化:避免不必要的请求
如果筛选器对象包含多个字段,部分字段变化不影响请求,可以用useMemo缓存处理后的参数,减少无效请求:
import { useMemo } from 'react'; // ... const filtersQueryParam = useMemo(() => { // 过滤空值或不需要的字段,生成稳定的请求参数 return Object.fromEntries( Object.entries(filters).filter(([_, value]) => value !== '') ); }, [filters]); const { data, error, isLoading } = useGetDataQuery(filtersQueryParam);
内容的提问来源于stack exchange,提问作者PttRulez
相关产品推荐
相关产品推荐

