从 Flux 到 Redux:重构 React 应用的指南

阅读时长 17 分钟读完

从 Flux 到 Redux:重构 React 应用的指南

随着 React 技术的发展,前端开发人员越来越倾向于使用 Flux 或 Redux 这样的数据流解决方案来构建复杂的应用程序。虽然 Flux 是 React 中最常见的数据流框架之一,但越来越多的开发人员开始使用 Redux 来构建他们的应用程序。

Redux 被认为是 Flux 的更高级别实现,它通过提供单一不可变状态树来管理复杂的应用程序,从而使数据管理变得更加简单。在本指南中,我们将介绍如何将一个 Flux 应用程序重构为一个 Redux 应用程序,并描述 Redux 的基本原则和设计模式,以及如何在 React 中使用 Redux。

一步步重构你的 Flux 应用

为了更好地了解如何在您的 React 应用程序中使用 Redux,我们将提供一个简单的 Flux 应用,并一步步将其重构为 Redux 应用程序。

假设您有以下初始 Flux 应用程序:

app.jsx

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

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

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

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

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

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

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

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

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

app-actions.js

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

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

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

app-constants.js

app-store.js

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

product-list.jsx

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

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

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

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

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

product.jsx

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

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

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

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

在这个 Flux 应用中,我们有一个简单的购物车,用户可以将产品添加到购物车中并查看订单总额。让我们考虑如何将其转换为 Redux 应用程序。

重构 Flux 应用为 Redux 应用

Redux 与 Flux 之间的主要区别在于它提供了一个单一的可调用对象,即 Redux Store,该对象存储应用程序的状态。Redux Store 包含以下内容:

  • State: 应用程序的当前状态
  • Action: 描述应用程序状态更改的纯 JavaScript 对象
  • Reducer: 描述状态如何响应操作的函数,接受当前状态和操作,并返回新状态的函数

我们将使用此模式重构 Flux 应用。让我们开始编写 Redux 应用的新入口点:index.jsx

index.jsx

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

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

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

在这里,我们导入了 react-redux 中的 ProvidercreateStore 方法,以及我们应用程序的根 App 组件。我们使用 createStore 方法创建了 Redux Store,并将其作为参数传递给 Provider 组件,以使整个应用程序都可以访问 Store 中的状态数据。现在让我们看一下我们的新 app.jsx 组件。

app.jsx

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

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

我们已经将所有关于 Flux Store 和 Action 的细节从 App 组件中移除,因为这些细节现在会作为将与 Store 和 Actions 相关的状态作为属性传递给子组件的方式来呈现。

接下来,我们将定义 actions 和 reducers,以描述应用程序中的状态与状态变化。

actions.js

reducers.js

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

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

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

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

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

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

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

现在让我们看看不同的单个组件:product-list.jsxcart.jsx

product-list.jsx

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

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

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

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

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

在这里,我们开辟了一个新的组件级状态,products,并使用 -react-redux 中的 connect 方法将其绑定到父级 App 组件中的 Redux Store 上。

我们还定义了 addToCart 方法,并使用 connect 方法将其绑定到组件中。最后,我们将当前组件的 state 映射到 Store 的 state

cart.jsx

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

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

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

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

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

在这里,我们定义了一个新的 cart 组件,并将 itemstotal 映射到 Store 的状态中。现在让我们看看我们在 product.jsx 组件中发生了什么。

product.jsx

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

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

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

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

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

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

与之前的版本不同,我们将 onAddToCart 方法作为组件的 props 属性之一传递给子组件。因此,此组件现在可以称为“呈现组件”,它不知道任何有关 Flux 或 Redux 的内容。它只知道它如何渲染自己以及何时呼叫其他组件的方法。因此,这个组件是一个纯组件。

指导意义

通过以上演示,我们可以看到 Flux 和 Redux 都是优秀的数据流解决方案。但是,Redux 更加强大和有趣!Redux 改进了 Flux 的 Middleware 和 Store 的设计,提供了一个更优美的方式来管理不断变化的应用程序状态。

重构 Flux 应用程序以使用 Redux 很容易,因为 Redux 特别设计用于完全兼容 Flux 架构。我们可以通过编写拆分我们的应用程序逻辑成适当的 Actions 和 Reducers 代码块来增强应用程序的可读性和可维护性。

在设计 Redux 应用程序时,请记住以下准则:

  • Store 中的状态应该是不可变的,这样才能保证应用程序状态的可重现性。
  • 关于应用程序的状态变化发生的原因必须是一个 Action 对象。即,Redux 框架中的 Action 模型是在传递必要的信息的同时,保证更新状态数据可回溯构成。
  • Reducers 是纯函数,一定得是“无副作用”和容易测试的功能。让 reducer始终保持一致,并不是针对某个操作实现计算和存储,只要 Action 利用处理的模型中,实现对应仅仅的变化即可。
  • 进行“异构”数据序列化或者本地存储的操作是通过应用 Middleware 实现的。例如,Redux 让我们使用 Immutable.js 库的深层次值(类似 JSON 的对象)有状态检查/修复/传递的方式。

以上是 Redux 应用程序的基本设计规则。遵守这些原则可以帮助我们编写可维护和可预测的代码,在团队开发中将产生许多好处。

本文演示了如何使用一个“简单”的 Flux 应用程序为例来重构应用程序以实现更加灵活和可预测的 Redux 应用。

是的,人人都能使用并喜欢Redux。它提供了一个方便的开发范式,通过组合应用程序中的每个部分,从而使它更容易理解和维护。简而言之,Redux 是一种使您的 React 应用程序更好、更高效和更容易理解的方式。

附:示例代码

https://codesandbox.io/s/trendingweather-bbnhu

完成对指南的撰写,欢迎检查。

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

纠错
反馈

纠错反馈