ES6增强对象字面量在Redux reducer中异常:files返回空对象
嘿,我之前也踩过这个坑!让我帮你一步步排查问题~
首先,先还原下你遇到的场景:用ES6对象字面量简写语法组合reducers时,auth、form都正常,但files对应的状态总是空对象;换成files: files这种传统键值对写法就正常工作。
核心原因:90%的概率是导入导出不匹配或者变量名与键名不对应
ES6对象简写的规则是:当对象的键名和变量名完全一致时,才能省略冒号和右侧变量。比如const files = myReducer; { files }等价于{ files: files }——但前提是files这个变量确实是你的reducer函数,而不是undefined或者其他值。
Redux的combineReducers如果收到undefined作为reducer,会自动把该状态初始化为空对象,这就是你看到的现象。而你用传统写法时,可能无意中修正了变量名的问题,所以状态正常。
一步步排查与解决
1. 先检查files_reducer.js的导出方式
打开你的files_reducer.js,看它是默认导出还是命名导出:
如果是默认导出:
// files_reducer.js const initialState = { items: [], loading: false }; export default (state = initialState, action) => { switch(action.type) { // 你的reducer逻辑 default: return state; } }那导入时必须用默认导入,并且变量名要和简写的键名一致:
// rootReducer.js import { combineReducers } from 'redux'; import auth from './auth_reducer'; import files from './files_reducer'; // 这里变量名是files,和简写键名一致 const rootReducer = combineReducers({ auth, files // 简写有效,状态正常 });如果是命名导出:
// files_reducer.js const initialState = { items: [], loading: false }; export const filesReducer = (state = initialState, action) => { switch(action.type) { // 你的reducer逻辑 default: return state; } }那要么重命名导入变量,要么在combineReducers里写完整键值对:
// 方式一:重命名导入,用简写 import { combineReducers } from 'redux'; import auth from './auth_reducer'; import { filesReducer as files } from './files_reducer'; // 重命名为files const rootReducer = combineReducers({ auth, files // 简写有效 }); // 方式二:完整键值对写法 import { combineReducers } from 'redux'; import auth from './auth_reducer'; import { filesReducer } from './files_reducer'; const rootReducer = combineReducers({ auth, files: filesReducer // 传统写法,正常工作 });
2. 检查reducer的初始状态是否设置正确
如果你的files reducer没有给state设置默认值,比如:
// 错误写法:没有初始状态默认值 export default (state, action) => { switch(action.type) { // ... } }
那Redux初始化时state会是undefined,combineReducers会自动把它转换成空对象——这种情况不管用简写还是传统写法都会有问题,所以一定要给state设置默认初始值:
// 正确写法:设置初始状态 const initialState = { items: [], loading: false }; export default (state = initialState, action) => { switch(action.type) { // ... default: return state; } }
3. 确认变量名没有拼写错误
有时候只是简单的拼写失误:比如导入的变量是fileReducer(少了个s),但简写时写的是files,这时候files变量根本不存在,会被当作undefined传入combineReducers,导致状态为空。
验证方法
你可以在combineReducers之前加个console.log,看看files变量是不是你的reducer函数:
import files from './files_reducer'; console.log(files); // 如果输出是函数,说明导入正确;如果是undefined,说明导入出问题了
内容的提问来源于stack exchange,提问作者Michael Lee

