【问题标题】:React-redux store updates but React does notReact-redux 存储更新,但 React 没有
【发布时间】:2016-01-13 09:47:29
【问题描述】:

请耐心等待,因为这个问题与我使用 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 action React 将赶上并正确显示所有 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 repo:

Deployment bank demo

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

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

我已经给他们一个键prop 设置为它的索引。不过,我怀疑这与我的问题有关。

【问题讨论】:

  • 嗯,我认为有两件事可以帮助缩小错误范围:1) 使用redux-logger 查看操作发生时发生的变化 2) 发布您的减速器、操作和 mapStateToProps 代码。
  • 不幸的是,我无法让 redux-logger 正常工作,但我已经自己记录了一些内容,并且那里的工作正常。我现在将使用 reducer、actions 和 mapStateToProps 更新问题。
  • React 如何判断状态是否改变?也许是因为状态对象的变化相当深,而且变化太小以至于无法重新渲染? react-redux 如何决定何时更新 React props?我刚刚在 mapStateToProps 中注销了 state 的值,它在那里更新了,只是没有在 React 中。
  • React Redux 使用引用相等检查。如果你改变状态,它不会看到变化。不要改变状态。

标签: javascript reactjs redux


【解决方案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 “Troubleshooting” 文档中有详细描述,所以我建议你阅读它们。

https://redux.js.org/troubleshooting

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

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

【讨论】:

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