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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:46:06