Redux初始状态显示为空(undefined)问题求助
问题描述
首页加载时尝试获取帖子数据,但Redux Store初始状态为空,不符合预期;但修改与Redux无关的代码后,Store又能正常显示帖子数据。
相关代码文件
postReducer.js
import { ActionTypes } from "../constants/action-types"; const initialState = { posts: [], }; const postReducer = (state = initialState, { type, payload }) => { switch (type) { case ActionTypes.SET_POSTS: return { ...state, posts: payload }; default: return state; } }; export default postReducer;
store.js
import { legacy_createStore as createStore } from "redux"; import reducers from "./reducers/index"; const store = createStore( reducers, {}, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() ); export default store;
home.js
const dispatch = useDispatch(); const fetchPosts = async () => { const response = await axios .get("https://fakestoreapi.com/products") .catch((err) => { console.log("error : ", err); }); dispatch(setPosts(response.data)); }; useEffect(() => { fetchPosts(); }, []);
重复的postAction.js(错误文件)
import { ActionTypes } from "../constants/action-types"; const postReducer = (state = [], { type, payload }) => { switch (type) { case ActionTypes.SET_POSTS: console.log("Here"); return { ...state, posts: payload }; default: return state; } }; export default postReducer;
Post.js
import { Avatar, Card, CardActions, CardContent, CardHeader, CardMedia, Checkbox, IconButton, Typography, } from "@mui/material"; import ShareIcon from "@mui/icons-material/Share"; import MoreVertIcon from "@mui/icons-material/MoreVert"; import Favorite from "@mui/icons-material/Favorite"; import { FavoriteBorder } from "@mui/icons-material/FavoriteBorder"; import { useSelector } from "react-redux"; const Post = () => { const posts = useSelector((state) => state.allPosts.posts); console.log(posts); const renderList = posts.map((post, key) => { return ( <Card sx={{ marginBottom: "10px" }} key={key}> <CardHeader avatar={ <Avatar sx={{ bgcolor: "red" }} aria-label="recipe"> R </Avatar> } action={ <IconButton aria-label="settings"> <MoreVertIcon /> </IconButton> } title="John" subheader={post.updatedAt} /> <CardMedia component="img" height="20%" image={post.image} alt="Paella dish" /> <CardContent> <Typography variant="body2" color="text.secondary"> {post.description} </Typography> </CardContent> <CardActions disableSpacing> <IconButton aria-label="add to favorites"> <Checkbox icon={<FavoriteBorder />} checkedIcon={<Favorite sx={{ color: "red" }} />} /> </IconButton> <IconButton aria-label="share"> <ShareIcon /> </IconButton> </CardActions> </Card> ); }); return <> {renderList}</>; }; export default Post;
正确的postAction.js
import { ActionTypes } from "../constants/action-types"; export const setPosts = (posts) => { return { type: ActionTypes.SET_POSTS, payload: posts, }; }; export const selectedPost = (post) => { return { type: ActionTypes.SELECTED_POST, payload: post, }; };
index.js
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import { Provider } from "react-redux"; import store from "../src/redux/store"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> );
问题根源及修复方案
1. Store初始化覆盖了Reducer初始状态
store.js中createStore的第二个参数传入空对象{},直接覆盖了所有reducer定义的初始状态,导致allPosts.posts的初始状态失效。
修复:
删除createStore的第二个参数,让reducer的初始状态生效:
const store = createStore( reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() );
2. 存在重复且命名错误的Reducer文件
命名为postAction.js的文件实际是reducer代码,容易导致代码混淆,若被错误引入根reducer,会覆盖正确的postReducer逻辑。
修复:
- 删除该重复文件,仅保留
postReducer.js处理帖子状态 - 检查根reducer(
./reducers/index),确认只引入正确的postReducer并命名为allPosts(匹配组件中state.allPosts.posts的取值路径)
3. React StrictMode导致的开发模式异常
<React.StrictMode>在开发模式下会触发两次组件挂载,包括useEffect执行。第一次请求未完成时组件已渲染,Store为空;修改代码热重载后,请求已完成,Store有数据。
修复(可选):
开发阶段可暂时移除<React.StrictMode>避免重复执行:
root.render( <Provider store={store}> <App /> </Provider> );
4. 请求错误处理的潜在问题
home.js中若请求失败,response为undefined,执行dispatch(setPosts(response.data))会报错。
修复:
改用try/catch确保仅在请求成功时分发action:
const fetchPosts = async () => { try { const response = await axios.get("https://fakestoreapi.com/products"); dispatch(setPosts(response.data)); } catch (err) { console.log("error : ", err); } };
内容的提问来源于stack exchange,提问作者Shiv Shankar Prasad
相关产品推荐
相关产品推荐

