使用RTK Query+React+Material UI实现商品搜索过滤遇错求助
商品搜索过滤功能修复
问题描述
使用fakestoreapi实现商品搜索过滤,输入框能获取值但功能失效,控制台抛出Uncaught TypeError: Cannot read properties of undefined (reading 'filter')错误,根源是API请求未完成时data为undefined,直接调用filter方法导致报错。
修复方案
1. 增加API状态判断
在渲染搜索结果前,先判断数据是否加载完成,避免在data为undefined时执行过滤逻辑。
2. 优化过滤逻辑并缓存结果
用useMemo缓存过滤后的结果,避免每次渲染都重复执行过滤操作,同时给data添加空值兜底。
3. 调整组件传参方式
直接将过滤后的结果传给SearchResult组件,而非传递函数,简化组件逻辑。
修改后的代码
SearchInput.jsx
import React, { useState, useMemo } from 'react' import { Box, TextField, InputAdornment, CircularProgress, Typography } from "@mui/material"; import SearchIcon from "@mui/icons-material/Search"; import { useGetAllProductsQuery } from '../../services/features/api/shopApiSlice'; import { SearchResult } from '../../components/Search'; export const SearchInput = () => { const [searchProduct, setSearchProduct] = useState(""); const { data, error, isError, isLoading, isFetching } = useGetAllProductsQuery(); const handleChangeSearch = (event) => { const { value } = event.target setSearchProduct(value); }; // 用useMemo缓存过滤结果,仅当data或searchProduct变化时重新计算 const filteredProducts = useMemo(() => { // 数据未加载时返回空数组 if (!data) return []; return data.filter((product) => { return product.title.toLowerCase().includes(searchProduct.toLowerCase()); }); }, [data, searchProduct]); // 加载状态提示 if (isLoading || isFetching) { return <CircularProgress />; } // 错误状态提示 if (isError) { return <Typography color="error">加载商品失败:{error?.message}</Typography>; } return ( <Box component="form" noValidate > <TextField type="search" size='small' sx={{ width: "100%", }} id="pesquisar-produto" placeholder="Pesquisar" value={searchProduct} onChange={handleChangeSearch} InputProps={{ startAdornment: ( <InputAdornment position="start"> <SearchIcon /> </InputAdornment> ) }} /> <SearchResult products={filteredProducts}/> </Box> ) }
SearchResult.jsx
import React from 'react'; import { Box, Typography } from '@mui/material'; export const SearchResult = ({ products }) => { // 无匹配结果时提示 if (products.length === 0) { return <Typography variant="body2">未找到匹配的商品</Typography>; } return ( <Box> {products.map((product) => { return ( <Box key={product.id}> <li>{product.title}</li> </Box> ); })} </Box> ) }
关键说明
- 新增了加载和错误状态的UI提示,提升用户体验
- 用
useMemo缓存过滤结果,减少不必要的计算,优化性能 - 给
data添加了空值判断,彻底解决undefined.filter的报错问题 - 调整了组件传参逻辑,让
SearchResult组件更专注于渲染结果,职责更清晰
内容的提问来源于stack exchange,提问作者Begginer
相关产品推荐
相关产品推荐

