2015-10-15 110 views
29

忍受我在这里,因为这个问题涉及我的第一个测试应用程序使用React,Redux或react-redux。 Docs让我走得很远,我有一个模拟银行应用程序,主要工作。我的状态对象看起来大致是这样的:React-redux商店更新但React不是

{ 
activePageId: "checking", 
accounts: [ 
    checking: { 
    balance: 123, 
    transactions: [ 
     {date, amount, description, balance} 
    ] 
    } 
] 
} 

我只有两个动作:

CHANGE_HASH(如URL哈希)。这个动作总是按预期工作,所有reducer所做的就是更新state.activePageId(是的,我克隆了状态对象而不是修改它)。行动之后,我可以看到Redux商店中的状态发生了变化,我可以看到React已更新。

function changeHash(id) { 
     return { 
      type: "CHANGE_HASH", 
      id: id 
     } 
} 

2. ADD_TRANSACTION(表单提交)。此操作从不更新React,但始终更新Redux存储。此操作的缩减器正在更新state.accounts [0] .balance,并将事务对象添加到数组state.accounts [0] .transactions。我没有收到任何错误,React只是不更新​​。但是,如果我发送CHANGE_HASH动作,React将会赶上并正确显示所有ADD_TRANSACTION状态更新。

功能addTransaction(事务,平衡,帐户){ 返回{ 类型: “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/

附:我撒谎没有任何错误。我有一些警告“”警告:数组或迭代器中的每个孩子都应该有一个唯一的“键”prop ......“我已经给他们一个关键的道具来设置它的索引,我怀疑它有什么做我的问题虽然

+1

嗯,我想两件事情,将有助于缩小错误:1)使用[终极版记录器(https://github.com/fcomb/redux-logger),看看有什么变化时,行动发生2)发布你的reducer,action和mapStateToProps代码。 – Cheng

+0

不幸的是,我无法使用redux-logger工作,但我已经记录了我自己的事情,并且事情在那里按预期工作。我现在用reducer,actions和mapStateToProps来更新这个问题。 – curiouser

+0

React如何确定状态是否已更改?也许是因为状态对象中的变化相当深刻,变化非常小,所以不会重新渲染? react-redux如何决定何时更新React道具?我只是注销了mapStateToProps中的状态值,并且在那里更新,而不是在React中。 – curiouser

回答

44

的问题是在这一段代码:。

 // 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“Troubleshooting”文档中有详细描述,所以我建议您阅读它们。

https://redux.js.org/troubleshooting

我也建议你采取流量的比较终极版一看购物卡的例子,因为它说明如何在不以类似的方式变异他们你所要求的更新嵌套的对象。

https://github.com/voronianski/flux-comparison/tree/master/redux

+7

谢谢!我已经阅读了这些文档,并试图保留状态对象,但是我的误解在Object.assign方法中。虽然这是从初始对象创建一个新对象,但它只是一个浅层克隆,这意味着嵌套在状态对象中的对象不会被克隆,但仍然引用原始状态对象嵌套对象。因为没有嵌套的对象被修改,所以我没有遇到另一个操作的属性。关于对象克隆的一个很好的写法(#5是让我):http://blog.soulserv.net/understanding-object-cloning-in-javascript-part-i/ – curiouser

+7

这是正确的。一般来说,你不想深入克隆一切,因为它很昂贵。克隆你改变的部分。将reducer分解成许多函数以保持代码的可维护性。您可以从Redux回购中的“购物车”示例中获得灵感。 –