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

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

问题分析

  1. 分页逻辑依赖错误:当前分页计算(总页数、切片数据)均基于原始realestate数组,而非搜索后的filtered数组。切换页码后执行新搜索,filtered数组更新,但分页仍按原数组的页码范围切片,导致新搜索结果可能不在当前页码的切片范围内,显示空白。
  2. 未重置页码:搜索后未将当前页码重置为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:30:52