React Redux中多dispatch仅最后一个生效问题求助
React Redux中多次dispatch仅最后一个生效的问题解决
问题现象
在React Redux项目的action中连续调用两个dispatch时,始终只有最后一个dispatch的效果生效。调换两个dispatch的顺序后,依然是最后一个生效。
代码示例
示例1:仅最后一个SET_BLOGS的dispatch生效
import axios from "axios"; const setDataBlog = (page) =>{ return (dispatch) => { axios.get(`http://localhost:4000/api/blogs/?page=${page}&perPage=3`) .then(result => { const responseAPI = result.data dispatch({type: 'UPDATE_PAGE', payload: { currentPage: responseAPI.current_page, totalPage: responseAPI.total_page }}) // 此dispatch不生效 dispatch({type: 'SET_BLOGS', payload: responseAPI.data}) // 仅此生效 }) .catch(error => { console.log('error',error); }) } } export default setDataBlog
示例2:调换顺序后,仅最后一个UPDATE_PAGE的dispatch生效
import axios from "axios"; const setDataBlog = (page) =>{ return (dispatch) => { axios.get(`http://localhost:4000/api/blogs/?page=${page}&perPage=3`) .then(result => { const responseAPI = result.data dispatch({type: 'SET_BLOGS', payload: responseAPI.data}) // 此dispatch不生效 dispatch({type: 'UPDATE_PAGE', payload: { currentPage: responseAPI.current_page, totalPage: responseAPI.total_page }}) // 仅此生效 }) .catch(error => { console.log('error',error); }) } } export default setDataBlog
Home组件调用action代码
import { useEffect} from "react"; import CardBlog from "../components/CardBlog"; import Pagination from "../components/Pagination"; import {useDispatch, useSelector} from 'react-redux' import {setDataBlog} from '../redux/action' const Home = () => { const {dataBlog, page} = useSelector(state => state.homeReducer); const dispatch = useDispatch(); // 检查是否生效 console.log('page', page); useEffect(() => { dispatch(setDataBlog(1)) }, [dispatch]) return ( <div className="max-w-screen-xl mx-auto px-4 py-16 sm:px-6 lg:px-8"> <div className=" md:grid md:grid-cols-2 lg:grid-cols-3"> {dataBlog?.map(blog => ( <CardBlog key={blog._id} image={`http://localhost:4000/${blog.image}`} title={blog.title} body={blog.body} author={blog.author} date={blog.createdAt}/> ))} </div> <div> <Pagination/> </div> </div> ); } export default Home;
问题原因及解决方法
核心原因
这种问题几乎都是reducer的写法不符合Redux要求导致的:
- 直接修改原state对象,而非返回新的状态对象,Redux无法检测到状态变化;
- 返回新状态时没有合并原state的其他属性,导致前一个dispatch的状态被后一个覆盖。
错误的reducer示例(导致问题的写法)
const initialState = { dataBlog: [], page: { currentPage: 1, totalPage: 1 } }; // 错误写法1:直接修改原state function homeReducer(state = initialState, action) { switch(action.type) { case 'UPDATE_PAGE': state.page = action.payload; // 直接修改原state,Redux不识别状态变化 return state; case 'SET_BLOGS': state.dataBlog = action.payload; // 同样直接修改原state return state; default: return state; } } // 错误写法2:返回时未合并原state,覆盖整个状态 function homeReducer(state = initialState, action) { switch(action.type) { case 'UPDATE_PAGE': return action.payload; // 直接返回payload,丢失dataBlog case 'SET_BLOGS': return { dataBlog: action.payload }; // 丢失page属性 default: return state; } }
正确的reducer写法
必须返回新的状态对象,且通过展开运算符合并原state的所有属性,只修改需要更新的部分:
const initialState = { dataBlog: [], page: { currentPage: 1, totalPage: 1 } }; function homeReducer(state = initialState, action) { switch(action.type) { case 'UPDATE_PAGE': return { ...state, // 展开原state,保留dataBlog等其他属性 page: action.payload }; case 'SET_BLOGS': return { ...state, // 保留page等其他属性 dataBlog: action.payload }; default: return state; } }
验证方法
修改reducer后,重新运行项目,查看组件中的console.log('page', page)是否能正确打印更新后的页码,同时dataBlog也能正常渲染。
内容的提问来源于stack exchange,提问作者Dwi
相关产品推荐
相关产品推荐

