我有这些文件:
numPadHandler(我的减速器(,configureStore(我的商店(,TestRedux(我的组件,尝试使用存储(和我的应用程序文件。
减速器:
// store/reducers/numpadReducers/numpadHandler
const initialState = { valueNumPad: "1" }
function numpadHandler(state = initialState, action) {
let nextState;
switch(action.type) {
case 'ADD_DIGIT':
nextState = state;
nextState.valueNumPad = nextState.valueNumPad + action.value;
console.log("reducer new state : " + state.valueNumPad);
return nextState;
default:
return state;
}
}
export default numpadHandler;
存储:
// store/configureStore
import { createStore } from 'redux';
import numpadHandler from './reducers/numpadReducers/numpadHandler';
export default createStore(numpadHandler);
组件:
// components/TestRedux
import React, { useState } from "react";
import { connect } from 'react-redux';
import Button from './Button';
const TestRedux = (props) => {
const handleClick = () => {
console.log("props value numpad : " + props.valueNumPad);
const action = { type: "ADD_DIGIT", value: 5 }
props.dispatch(action);
}
return (
<div>
<Button onClick={handleClick} />
</div>
);
}
const mapStateToProps = (state) => {
console.log("state : " + state.valueNumPad);
return state
}
export default connect(mapStateToProps)(TestRedux);
应用程序:
//...
render() {
return (
<Provider store={ Store }>
<TestRedux />
</Provider>
);
}
我不明白为什么当我点击按钮时,reducer的状态正在改变,但函数mapStateToProps没有再次调用。
页面加载后有我的控制台输出:
state : 1
点击一次后:
props value numpad : 1
reducer new state : 15
点击两次后:
props value numpad : 1
reducer new state : 155
点击2次后完成控制台输出:
state : 1
props value numpad : 1
reducer new state : 15
props value numpad : 1
reducer new state : 155
所以你可以看到动作正在发生,reducer状态正在更新,但组件端没有更新!
你能解释一下为什么吗?
已解决:基于TLadd响应的回答:
我的reducer代码是错误的,这是编码的好方法:
case 'ADD_DIGIT':
const nextState = {
...state,
valueNumPad: state.valueNumPad + action.value
};
return nextState
问题出在减速器中:
case 'ADD_DIGIT':
nextState = state;
nextState.valueNumPad = nextState.valueNumPad + action.value;
console.log("reducer new state : " + state.valueNumPad);
return nextState;
Redux的工作原理是假设所有的状态变化都是不可变的。此选项允许它在决定应用程序的哪些部分需要重新呈现以响应正在调度的操作时使用浅相等检查。在上面的reducer情况下,将state指定给nextState,并将新值直接指定给nextState.valueNumPad
。即使nextState
是一个新的参考,它仍然指原始状态,结果是原始状态的突变。
正确的做法是:
case 'ADD_DIGIT':
const nextState = {
...state,
valueNumPad: state.valueNumPad + action.value
};
return nextState
在这种情况下,我使用扩展符号...state
复制状态,并覆盖该副本中的valueNumPad
值。返回的nextState
是一个新对象,我根本没有对旧的state
对象进行任何更改。