React-redux 存储更新但 React 没有

IT技术 javascript reactjs redux
2021-04-05 18:45:09

请耐心等待,因为这个问题与我使用 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 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我谎称没有任何错误。我确实有很多警告

""警告:数组或迭代器中的每个子项都应该有一个唯一的“键”属性..."

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

1个回答

问题出在这段代码中:

// 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 比较中的 Shopping Card 示例,因为它显示了如何更新嵌套对象而不以与您要求的方式类似的方式对其进行变异。

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

没错。通常,您不想深度克隆所有内容,因为它很昂贵。只需克隆您更改的部分。将 reducer 拆分为多个函数以保持代码的可维护性。您可以从 Redux 存储库中的“购物车”示例中获取灵感。
2021-06-18 18:45:09
谢谢!我已经阅读了这些文档并试图保留状态对象,但是我的误解是在 Object.assign 方法中。虽然这是从初始对象创建一个新对象,但它只是一个浅层克隆,这意味着嵌套在状态对象中的对象没有被克隆,但仍然引用原始状态对象的嵌套对象。我没有通过另一个操作遇到此属性,因为没有修改嵌套对象。一篇关于对象克隆的好文章(#5 是我的灵感来源):blog.soulserv.net/...
2021-06-20 18:45:09