解决 Redux 报错问题:错误地尝试更改 Redux 状态

阅读时长 7 分钟读完

当我们在使用 Redux 进行状态管理时,有时会遇到 Redux 报错问题:错误地尝试更改 Redux 状态。这个错误看起来比较晦涩,不太容易理解,本文将围绕这个主题,详细解决这个报错问题并提供示例代码。

什么是“错误地尝试更改 Redux 状态”?

这个错误提示通常在开发 Redux 应用时出现,它的含义是:某个组件尝试修改 Redux 中的状态,而不是使用 Redux 的 action&reducer 机制来进行状态改变,从而导致了这个错误。

为什么会出现这个错误?

Redux 的核心思想是:所有的 State 都保存在 Store 对象中,而任何的 State 修改操作,必须通过 dispatch Action 的方式来进行。这样做的目的是为了保证状态的可预测性,避免了各个组件之间直接修改 State 导致的意料之外的问题。

我们知道,Redux 中的 State 变化是由 reducer 来处理的,reducer 接收到一个旧的 State 和新的 Action,根据 Action 的类型返回一个新的 State。而我们在 reducer 中修改的 State 不仅仅是一个普通的对象,它是由 Redux 的 createStore 方法产生的一个 immutable 对象。因此,在 reducer 中修改 State 时,需要使用较为复杂的更新方式,比如 Object.assign、Object.freeze、不可变数据等技术手段,否则会被 Redux 拒绝,返回一个新的状态给 Store,使得所有订阅了这个状态的组件都能够实时接受到这个更新。

而如果组件直接修改了 State,Redux 无法知道这个修改操作,就会认为状态被非法篡改,就会报出“错误地尝试更改 Redux 状态”的错误信息。

如何解决这个问题?

如果你在使用 Redux 过程中遇到了这个问题,可以采用下面两种方式来解决。

方式一:确保所有的修改均通过 Action 和 reducer

在 React 组件中,我们应当遵循单向数据流的模式,即父传子通过 props 传递数据,子通过调用 props 中传入的函数来触发事件。如果父组件需要修改 State 中的数据,并影响到子组件的显示,我们需要采用 Redux 的方式来进行状态管理。

可以通过以下方式来做到:

  • 定义 action 类型以及对应的 action 创建函数
  • 定义 reducer 来修改 state 对象
-- -------------------- ---- -------
-------- ----------- - --- ------- -
  ------ ------------- -
    ---- ---------
      ------ -
        ---------
        -
          ----- ------------
          ---------- -----
        -
      --
    --------
      ------ ------
  -
-
展开代码
  • 在组件中引用上面定义的 action 创建函数,并使用 dispatch 函数来触发 action

方式二:使用 Redux 中间件来实现异步状态管理

有些情况下,我们需要异步地修改 State 中的数据,而异步操作通常是通过 Ajax 请求或者一些耗时的计算操作来实现的,这时候通过 Action 和 reducer 来修改 State 就不方便。为此,Redux 中提供了中间件机制来管理异步操作。

可以通过以下方式来实现:

  • 定义一个异步操作的 action 创建函数
  • 实现中间件,用来处理异步操作
-- -------------------- ---- -------
------ --------------- ---- -------------
------ - ------------ --------------- - ---- -------
------ ----------- ---- ------------

----- ----- - ------------
  ------------
  ----------------
    ---------------
  -
-
展开代码

当使用中间件时,我们可以在 action 的函数中进行异步操作,中间件会在 action 到达 reducer 之前,把异步操作的结果做为 payload 附加到 action 上,这样,我们就可以在 reducer 中处理这个 payload,在 store 中更新 state 了。这样就避免了直接修改 state 来更新状态导致的问题。

示例代码

以下是在 React 组件中使用 Redux 的 TotoList 示例代码,使用方式一来解决报错问题:

-- -------------------- ---- -------
------ ------ - --------- - ---- -------
------ - ------- - ---- --------------

----- -------- ------- --------- -

  ---------------- -
    --- ---- - --------------------
    -------------------------
  -

  -------- -
    ------ -
      -----
        -------- ---------
        ------- -------------------------------------------- -------------
        ----
          ---------------------------- ------ --
            --- ----------------------------
          --
        -----
      ------
    -
  -
-

----- --------------- - ----- -- --
    ------ -----------
---
----- ------------------ - -------- -- --
    -------- ---- -- ------------------------
---

------ ------- ------------------------ -----------------------------
展开代码

在上面的代码中,我们通过 connect 方法把组件和 store 建立起连接,然后在组件中使用 props 来触发状态变化,遵循了单向数据流的模式。这样就可以避免直接修改 state 的问题。

总结

在 Redux 中,我们需要始终遵循 Action 和 reducer 的机制,确保每一个状态变化都是经过 action 创建函数和 reducer 处理过的,否则会导致“错误地尝试更改 Redux 状态”的问题。当需要进行异步操作时,使用中间件来处理会比较方便。遵循 Redux 框架提供的方式,能够有效地保护状态可预测性,快速定位问题,对代码的可维护性和代码质量有重要作用。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65926e6eeb4cecbf2d73ac77

纠错
反馈

纠错反馈