React-Redux搜索功能Action无限调用问题求助
问题:React-Redux搜索功能触发Action无限调用
我在使用React-Redux实现搜索功能时,每次搜索数据都会导致Redux无限调用Action。虽然能返回正确结果,但会触发无限次调用,甚至出现undefined的情况。请问该如何解决这个问题?
Action
export const SEARCH_PRO = (query) =>{ return { type: SEARCH_PROS, query, } }
Reducer
export const productData = (state = { searchDatas: [] }, action) => { switch (action.type) { case SEARCH_PROS: console.warn("PRODUCT_LIST condition ", action.searchProds) return {searchDatas:[action.searchProds]} default: return state } }
Saga
function* searchProducts(data) { let result = yield fetch(`products/searchpro?search=${data.query}`); result = yield result.json(); console.warn("products action is called", result) console.warn("products action is ", data.query) yield put({type: SEARCH_PROS, searchProds:result.products.data}) } export function* productSaga() { yield takeEvery(SEARCH_PROS, searchProducts) }
搜索组件
<input type="search" className="form-control" name="search" placeholder="Search your Products" onChange={(event) => dispatch(SEARCH_PRO(event.target.value))} />
问题原因与解决方法
核心原因
你的代码里同一个SEARCH_PROS类型被同时用作「触发搜索请求的Action」和「接收搜索结果的Action」:Saga监听SEARCH_PROS发起请求,请求完成后又dispatch了同类型的Action,导致Saga再次监听、再次发起请求,形成无限循环。
具体修复步骤
拆分Action类型
新增一个专门用于接收搜索结果的Action类型,让原SEARCH_PROS只负责触发请求:// Action定义 export const SEARCH_PRO = (query) => ({ type: 'SEARCH_PROS', query }) export const SEARCH_PROS_SUCCESS = (searchProds) => ({ type: 'SEARCH_PROS_SUCCESS', searchProds })修改Reducer逻辑
让Reducer只响应SEARCH_PROS_SUCCESS来更新状态,同时保留原状态的其他字段:export const productData = (state = { searchDatas: [] }, action) => { switch (action.type) { case 'SEARCH_PROS_SUCCESS': console.warn("PRODUCT_LIST condition ", action.searchProds) return { ...state, searchDatas: action.searchProds } default: return state } }注:原代码里
[action.searchProds]会把结果额外包成数组,可能导致数据结构错误,这里直接赋值action.searchProds即可。调整Saga逻辑
Saga监听SEARCH_PROS,请求完成后dispatchSEARCH_PROS_SUCCESS而非原类型,同时添加异常捕获避免请求崩溃:function* searchProducts(data) { try { let result = yield fetch(`products/searchpro?search=${data.query}`); result = yield result.json(); console.warn("products action is called", result) console.warn("products action is ", data.query) yield put({type: 'SEARCH_PROS_SUCCESS', searchProds: result.products.data}) } catch (error) { console.error('搜索请求失败:', error) } } export function* productSaga() { yield takeEvery('SEARCH_PROS', searchProducts) }优化搜索组件(可选)
给输入框添加防抖处理,避免每输入一个字符就发起请求,减少无效请求:import { useCallback, useState } from 'react' const debounce = (func, delay) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } const SearchComponent = () => { const dispatch = useDispatch(); const debouncedSearch = useCallback(debounce((query) => { dispatch(SEARCH_PRO(query)) }, 300), [dispatch]) return ( <input type="search" className="form-control" name="search" placeholder="搜索你的产品" onChange={(event) => debouncedSearch(event.target.value)} /> ) }
内容的提问来源于stack exchange,提问作者Md. Ashikur Rahman
相关产品推荐
相关产品推荐

