47

请耐心等待,因为这个问题与我使用 React、Redux 或 react-redux 的第一个测试应用程序有关。Docs 让我走得很远,我有一个模拟银行应用程序,大部分都可以工作。我的状态对象大致如下:

{
 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 actionReact 将赶上并ADD_TRANSACTION正确显示所有状态更新。

function addTransaction(transaction, balance, account) {
    return {
        type: "ADD_TRANSACTION",
        payload: {
            transaction: transaction,
            balance: balance,
            account: account
        }
    }
}

我的减速机...

    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 store更新而更新。

Github 仓库:

部署银行演示

ps 我谎称没有任何错误。我确实有很多警告

""警告:数组或迭代器中的每个子元素都应该有一个唯一的 "key" 属性..."

我已经给他们一个键prop集到它的索引。我怀疑这与我的问题有关。

4

1 回答 1

60

问题出在这段代码中:

// 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

我还建议您看一下 Flux Comparison for Redux 中的 Shopping Card 示例,因为它展示了如何更新嵌套对象而不以类似于您所要求的方式改变它们。

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

于 2015-10-16T10:14:47.930 回答