如何使用Redux Toolkit、React和JavaScript实现全局搜索筛选?
问题:如何将API返回的商品数组存入Redux的initialState并实现搜索筛选
我需要开发一个基于商品标题的全局搜索筛选功能,用Redux管理全局状态,已经创建了用于筛选标题的reducer,但不知道怎么把API返回的对象数组存入initialState的data数组中;调用API用的是Redux Toolkit的createAPI。
现有代码
searchSlice 代码
import { createSlice } from "@reduxjs/toolkit"; const searchSlice = createSlice({ name: "search", initialState: { data: [], // 用于存储API返回的对象数组 filteredTitle: [], isLoading: true }, reducers: { getData: (state, action) => { state.data = action.payload; }, searchByName: (state, action) => { const filteredResult = state.data.filter((product) => product.title.toLowerCase().includes(action.payload.toLowerCase()) ); return { ...state, filteredTitle: action.payload.length > 0 ? filteredResult : [...state.data] }; } } }); export const { searchByName, getData } = searchSlice.actions; export default searchSlice.reducer;
App.js 代码
import React, { useState, useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { searchByName, getData } from "./features/slice"; import { useGetAllProductsQuery } from "./services/api"; export default function App() { const dispatch = useDispatch(); const filteredTitle = useSelector((state) => state.search.filteredTitle); const [searchTerm, setSearch] = useState(""); const { data } = useGetAllProductsQuery(); console.log("data", data); const changeSearchTerm = (e) => { setSearch(e.target.value); }; useEffect(() => { dispatch(searchByName(searchTerm)); dispatch(getData(data)); }, [searchTerm, dispatch]); return ( <div> <input onChange={changeSearchTerm} type="text" value={searchTerm} /> <div> {filteredTitle.map((user) => ( <div>{user.name}</div> ))} </div> </div> ); }
解决方案
1. 修正API数据的存储时机
当前代码在搜索词变化时才尝试存储API数据,会导致data初始为undefined时存入错误值。需要单独监听data的变化,确保数据存在时再存入Redux:
// App.js 中修改 useEffect useEffect(() => { // 仅当API返回有效数据时,存入Redux if (data) { dispatch(getData(data)); } }, [data, dispatch]); // 单独处理搜索逻辑,仅在搜索词变化时触发筛选 useEffect(() => { dispatch(searchByName(searchTerm)); }, [searchTerm, dispatch]);
2. 优化Redux Slice的reducer逻辑
Redux Toolkit支持直接修改state(内部会自动处理不可变更新),可以简化searchByName的写法:
// searchSlice 中修改 searchByName reducer searchByName: (state, action) => { const searchValue = action.payload.toLowerCase(); // 根据搜索词筛选,无搜索词时返回全部数据 state.filteredTitle = searchValue ? state.data.filter(product => product.title.toLowerCase().includes(searchValue)) : [...state.data]; }
3. 修正渲染字段错误
当前渲染的user.name与API返回的商品字段不符,应改为product.title,同时添加唯一key:
// App.js 中修改渲染部分 {filteredTitle.map((product) => ( <div key={product.id}>{product.title}</div> ))}
4. 处理初始加载状态(可选)
可以利用RTK Query的isLoading状态来优化用户体验:
// App.js 中解构RTK Query的状态 const { data, isLoading } = useGetAllProductsQuery(); // 渲染时添加加载提示 if (isLoading) return <div>加载中...</div>;
内容的提问来源于stack exchange,提问作者Begginer
相关产品推荐
相关产品推荐

