Angular 5结合@angular-redux/store点击递增按钮出现NaN问题求助
嘿,我来帮你搞定这个NaN的问题!结合你用的Angular 5、@angular-redux/store@7.1.0和redux@3.7.2,还有之前加了ChangeDetectionStrategy.OnPush的情况,咱们一步步排查:
这是导致NaN最常见的原因!如果你的store.ts里初始state没给count设置数值类型的默认值,第一次递增时就会出现undefined + 1 = NaN的情况。
❌ 错误示范:
// store.ts const initialState = { count: undefined // 或者根本没写count属性 };
✅ 正确写法:
// store.ts const initialState = { count: 0 // 必须是数值,比如0,不能是undefined/null };
要确保reducer函数传入了初始state,并且处理INCREMENT动作时正确计算新值:
❌ 错误示范(没传入初始state,或没解构原state):
// store.ts function counterReducer(state, action) { switch(action.type) { case 'INCREMENT': return { count: state.count + 1 }; // state初始为undefined时,state.count就是undefined default: return state; // 初始调用时state是undefined,直接返回会出问题 } }
✅ 正确写法:
// store.ts function counterReducer(state = initialState, action) { switch(action.type) { case 'INCREMENT': return { ...state, count: state.count + 1 }; // 解构原state,避免丢失其他属性 default: return state; } }
看你的app.component.ts里的mapStateToProps,是不是和你的Store结构匹配?比如如果Store的state嵌套了一层(比如{ counter: { count: 0 } }),但你直接取state.count,就会拿到undefined,进而显示NaN。
✅ 正确映射示例(对应你的Store结构):
// app.component.ts const mapStateToProps = (state) => { return { count: state.counter.count // 这里要和Store里的state层级完全一致 }; };
另外,因为你用了OnPush模式,要确保mapStateToProps返回的是新对象(比如上面的解构写法),这样Angular才能检测到引用变化触发更新。
确认你点击按钮时dispatch的动作类型,和reducer里的case完全一致,比如别把INCREMENT写成INCREASE——类型不匹配的话,reducer会返回原state,如果原state的count是undefined,还是会显示NaN。
✅ 正确的dispatch示例:
// app.component.ts increment() { this.store.dispatch({ type: 'INCREMENT' }); // 类型要和reducer里的case严格一致 }
你加OnPush解决了“Expression has changed after it was checked”的问题,这是因为OnPush减少了变更检测的频率,避免了Angular在检测周期后发现值变化的冲突。这个问题本身和当前的NaN无关,但如果后续还有更新不及时的情况,可以在组件里调用this.changeDetectorRef.markForCheck()手动触发变更检测。
内容的提问来源于stack exchange,提问作者Abhilash D K

