请耐心等待,因为这个问题属于我使用React,Redux或react-redux的第一个测试应用程序。文档已经让我走得很远,我有一个模拟银行应用程序,主要工作。我的状态对象看起来大致如下:
{
activePageId: "checking",
accounts: [
checking: {
balance: 123,
transactions: [
{date, amount, description, balance}
]
}
]
}
我只有两个动作:
1。 CHANGE_HASH(如在url哈希中)。此操作始终按预期工作,并且所有reducer都会更新state.activePageId(是的,我正在克隆状态对象而不是修改它)。在操作之后,我可以看到Redux商店中的状态已经发生变化,我可以看到React已经更新。
function changeHash(id) {
return {
type: "CHANGE_HASH",
id: id
}
}
2。 ADD_TRANSACTION(表单提交)。此操作永远不会更新React,但它始终更新Redux存储。此操作的reducer正在更新state.accounts [0] .balance并且它将一个事务对象添加到数组state.accounts [0] .transactions。我没有收到任何错误,React只是没有更新。但是,如果我调度CHANGE_HASH操作,React将赶上并正确显示所有ADD_TRANSACTION状态更新。
function addTransaction(transaction,balance,account){ 返回{ 键入:“ADD_TRANSACTION”, 有效载荷:{ 交易:交易, 平衡:平衡, 帐户:帐户 } } }
我的减速机......
function bankApp(state, action) {
switch(action.type) {
case "CHANGE_HASH":
return Object.assign({}, state, {
activePageId: action.id
});
case "ADD_TRANSACTION":
// get a ref to the account
for (var i = 0; i < state.accounts.length; i++) {
if (state.accounts[i].name == action.payload.account) {
var accountIndex = i;
break;
}
}
// is something wrong?
if (accountIndex == undefined) {
console.error("could not determine account for transaction");
return state;
}
// clone the state
var newState = Object.assign({}, state);
// add the new transaction
newState.accounts[accountIndex].transactions.unshift(action.payload.transaction);
// update account balance
newState.accounts[accountIndex].balance = action.payload.balance;
return newState;
default:
return state;
}
我的mapStateToProps
function select(state) {
return state;
}
我在这里缺少什么?我认为React应该在Redux商店更新时更新。
Github回购:https://github.com/curiousercreative/bankDemo 部署:http://curiousercreative.com/demos/bankDemo/
P.S。我撒谎没有任何错误。我确实有一些警告“”警告:数组或迭代器中的每个子项应该有一个唯一的“关键”道具......“我已经给它们一个关键的道具设置它的索引。我怀疑它有什么尽管如此。
答案 0 :(得分:54)
问题在于这段代码:
// clone the state
var newState = Object.assign({}, state);
// add the new transaction
newState.accounts[accountIndex].transactions.unshift(action.payload.transaction);
// update account balance
newState.accounts[accountIndex].balance = action.payload.balance;
克隆状态对象并不意味着您可以改变它所引用的对象。我建议你阅读更多关于不变性的内容,因为这不是它的工作原理。
在Redux“疑难解答”文档中详细介绍了此问题及其解决方案,因此建议您阅读它们。
https://redux.js.org/troubleshooting
我还建议你看一下Redux Flux Comparison中的购物卡示例,因为它展示了如何更新嵌套对象而不会以与你要求的方式类似的方式改变嵌套对象。
https://github.com/voronianski/flux-comparison/tree/master/redux