React+Redux-Toolkit中搜索与分页结合的异常问题求助
React+Redux-Toolkit搜索与分页结合的异常问题
问题现象
- 基础搜索功能正常:通过
filter方法筛选包含指定条件的对象数组,状态更新符合预期 - 异常场景:当筛选结果有2页及以上,切换到下一页后执行新搜索,UI显示空白列表;Dev-Tools显示状态已正确更新,但界面无内容
- 核心需求:每次执行搜索查询后,基于完整对象数组重新生成筛选列表,并确保分页逻辑正确适配新的筛选结果
搜索查询后的状态

相关代码
Reducer代码
const initialState = { realestate: [], isSuccess: false, isLoading: false, filtered: [], message: '', } export const estateSlice = createSlice({ name: 'realestate', // Reducer name initialState, reducers: { reset: () => initialState, filteredProperties: (state, action) => { let filtered = state.realestate.filter(el => el.located.includes(action.payload)) return {...state, filtered: filtered} } }, extraReducers: (builder) => { builder.addCase(getRealEstates.pending, (state) => { state.isLoading = true }) builder.addCase(getRealEstates.fulfilled, (state, action) => { state.isLoading = false state.isSuccess = true state.realestate = action.payload state.filtered = action.payload }) builder.addCase(getRealEstates.rejected, (state, action) => { state.isLoading = false state.isError = true state.message = action.payload }) } }) export const { filteredProperties, reset } = estateSlice.actions export default estateSlice.reducer
分类选择组件代码
const CategorySelect = () => { const dispatch = useDispatch() const changeSearch = (value) => { dispatch(filteredProperties(value.value)) } return ( <div className="selectMenus"> <div className="select">search options</div> <Select theme={customTheme} options={regions} placeholder="Region" className="selectBox" onChange={changeSearch} name={'Region'} /> </div> ) } export default CategorySelect
列表组件代码
const realestates = useSelector(state => state.realestate) let { isLoading, realestate, filtered, isError, message, isSuccess} = realestates; useEffect(() => { dispatch(getRealEstates()) if (realestate) { setShow(true) } else { console.log('No data retrieved') } }, [dispatch]) // pagination const pageNumbers = [] const resultsPerPage = 4 const pages = Math.ceil(realestate.length / resultsPerPage) for (let i = 1; i <= pages; i++) { pageNumbers.push(i) } const pagination = (number) => { setCurrentNumber(number) } const slicedList = useCallback(() => { const data2 = realestate.slice(((currentNumber - 1) * resultsPerPage), (currentNumber * resultsPerPage)) setNewList(data2) }, [currentNumber, realestate, resultsPerPage]) useEffect(() => { slicedList() }, [slicedList]) return ( <> <div className="borderTop"> <div className="border"></div> </div> <div className="sidebarContentWrapper"> <div className="sidebar"></div> <div className="content2"> <CategorySelect /> <ListItems newList={newList} show={show}/> <div className="btns"> {pageNumbers.map(number => { return <Pagination key={number} active={number === currentNumber} onClick={() => pagination(number)} title={number} /> })} </div> </div> <div className="sidebar2"></div> </div> </> ) } export default Content
问题分析
- 分页逻辑依赖错误:当前分页计算(总页数、切片数据)均基于原始
realestate数组,而非搜索后的filtered数组。切换页码后执行新搜索,filtered数组更新,但分页仍按原数组的页码范围切片,导致新搜索结果可能不在当前页码的切片范围内,显示空白。 - 未重置页码:搜索后未将当前页码重置为1,若之前切换到第N页(N>新搜索结果的总页数),切片后无数据返回。
解决方案
1. 调整分页逻辑为基于筛选后数组
修改列表组件中的分页相关代码,将所有依赖realestate的地方替换为filtered:
// 计算总页数时使用filtered数组长度 const pages = Math.ceil(filtered.length / resultsPerPage) // 切片函数使用filtered数组生成当前页数据 const slicedList = useCallback(() => { const data2 = filtered.slice(((currentNumber - 1) * resultsPerPage), (currentNumber * resultsPerPage)) setNewList(data2) }, [currentNumber, filtered, resultsPerPage])
2. 搜索后重置页码到第一页
在列表组件中监听filtered数组的变化,当搜索触发filtered更新时,自动重置当前页码为1:
useEffect(() => { setCurrentNumber(1); // 搜索后回到第一页 }, [filtered]);
3. 同步页码数组生成逻辑
更新页码数组的生成逻辑,确保基于筛选后的数组长度:
const pageNumbers = []; const pages = Math.ceil(filtered.length / resultsPerPage); for (let i = 1; i <= pages; i++) { pageNumbers.push(i); }
最终修改后的列表组件核心代码片段
const realestates = useSelector(state => state.realestate) let { isLoading, filtered, isError, message, isSuccess} = realestates; const [currentNumber, setCurrentNumber] = useState(1); const [newList, setNewList] = useState([]); const [show, setShow] = useState(false); useEffect(() => { dispatch(getRealEstates()) }, [dispatch]) // 监听数据加载完成,显示列表 useEffect(() => { setShow(filtered.length > 0); }, [filtered]) // pagination const resultsPerPage = 4 const pages = Math.ceil(filtered.length / resultsPerPage) const pageNumbers = Array.from({length: pages}, (_, i) => i + 1) const pagination = (number) => { setCurrentNumber(number) } const slicedList = useCallback(() => { const startIndex = (currentNumber - 1) * resultsPerPage; const endIndex = startIndex + resultsPerPage; const data2 = filtered.slice(startIndex, endIndex); setNewList(data2) }, [currentNumber, filtered, resultsPerPage]) // 搜索后重置页码 useEffect(() => { setCurrentNumber(1); }, [filtered]) useEffect(() => { slicedList() }, [slicedList])
内容的提问来源于stack exchange,提问作者Noud
相关产品推荐
相关产品推荐

