在Redux中使用外部API数据实现React搜索筛选功能求助
将Redux硬编码筛选数据替换为API数据(React + Redux Toolkit)
问题背景
我正在用React和Redux开发带筛选功能的搜索引擎,现在需要把Redux slice里硬编码的category、jobTypeList、datePost、experienceLavel、tags这些筛选数据,换成从外部API获取的数据。我对React和Redux不太熟悉,需要知道怎么把API数据传递给筛选器组件。
解决方案步骤
1. 调整初始状态
把初始状态里的硬编码数组改为空数组,同时新增加载、错误状态跟踪API请求过程:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; const initialState = { latestJob: [], category: [], jobTypeList: [], datePost: [], experienceLavel: [], tags: [], isLoading: false, error: null };
2. 创建异步Thunk封装API请求
用Redux Toolkit的createAsyncThunk处理API请求,若返回数据缺少isChecked字段,手动添加默认值:
// 替换为你的API接口地址 export const fetchFilterData = createAsyncThunk( 'job/fetchFilterData', async (_, { rejectWithValue }) => { try { const response = await fetch('你的API接口地址'); if (!response.ok) throw new Error('请求筛选数据失败'); const data = await response.json(); // 给需要复选状态的字段添加默认值 return { ...data, jobTypeList: data.jobTypeList.map(item => ({ ...item, isChecked: false })), datePost: data.datePost.map(item => ({ ...item, isChecked: false })), experienceLavel: data.experienceLavel.map(item => ({ ...item, isChecked: false })) }; } catch (err) { return rejectWithValue(err.message); } } );
3. 更新Slice处理异步状态
保留原有交互逻辑,新增extraReducers处理异步请求的三种状态:
export const jobSlice = createSlice({ name: "job", initialState, reducers: { addLatestJob: (state, { payload }) => { const isExist = state.latestJob?.includes(payload); if (isExist) { state.latestJob = state.latestJob.filter(item => item !== payload); } else { state.latestJob.push(payload); } }, clearJobTypeToggle: (state) => { state.jobTypeList?.forEach(item => item.isChecked = false); }, jobTypeCheck: (state, { payload }) => { const item = state.jobTypeList.find(item => item.id === payload); if (item) item.isChecked = !item.isChecked; }, datePostCheck: (state, { payload }) => { state.datePost.forEach(item => item.isChecked = item.id === payload); }, clearDatePostToggle: (state) => { state.datePost?.forEach(item => item.isChecked = false); }, experienceLavelCheck: (state, { payload }) => { const item = state.experienceLavel.find(item => item.id === payload); if (item) item.isChecked = !item.isChecked; }, clearExperienceToggle: (state) => { state.experienceLavel?.forEach(item => item.isChecked = false); }, }, extraReducers: (builder) => { builder .addCase(fetchFilterData.pending, (state) => { state.isLoading = true; state.error = null; }) .addCase(fetchFilterData.fulfilled, (state, { payload }) => { state.isLoading = false; state.category = payload.category; state.jobTypeList = payload.jobTypeList; state.datePost = payload.datePost; state.experienceLavel = payload.experienceLavel; state.tags = payload.tags; }) .addCase(fetchFilterData.rejected, (state, { payload }) => { state.isLoading = false; state.error = payload; }); } }); export const { addLatestJob, clearJobTypeToggle, jobTypeCheck, datePostCheck, clearDatePostToggle, experienceLavelCheck, clearExperienceToggle, } = jobSlice.actions; export { fetchFilterData }; export default jobSlice.reducer;
4. 在组件中触发请求并渲染筛选器
用useDispatch触发API请求,useSelector获取状态,渲染筛选组件:
import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { fetchFilterData, jobTypeCheck } from './path/to/jobSlice'; function FilterComponent() { const dispatch = useDispatch(); const { category, jobTypeList, datePost, experienceLavel, tags, isLoading, error } = useSelector(state => state.job); useEffect(() => { dispatch(fetchFilterData()); }, [dispatch]); if (isLoading) return <div>加载筛选数据中...</div>; if (error) return <div>加载失败:{error}</div>; return ( <div className="filter-container"> <div className="job-type-filter"> <h3>工作类型</h3> {jobTypeList.map(item => ( <label key={item.id}> <input type="checkbox" checked={item.isChecked} onChange={() => dispatch(jobTypeCheck(item.id))} /> {item.name} </label> ))} </div> {/* 其他筛选模块(分类、发布时间等)按同样逻辑渲染 */} </div> ); } export default FilterComponent;
关键注意事项
- 确保API返回的数据结构与原硬编码结构匹配,若有差异需在异步Thunk中做数据转换
- 原有筛选交互逻辑无需修改,只需替换数据来源
- 加载、错误状态的处理可避免数据未就绪时出现空筛选器或异常
内容的提问来源于stack exchange,提问作者Will Singleb
相关产品推荐
相关产品推荐

