Redux 已死:Redux 工具包万岁

2025-05-24

Redux 已死:Redux 工具包万岁

作者Victoria Lo

在本文中,我们来了解一下 Redux Toolkit,或者用开发团队的话来说,“官方的、自以为是的、功能齐全的高效 Redux 开发工具集”。

Redux 是什么以及它是如何工作的

大多数 Web 开发者可能都听说过 Redux,一个流行的状态管理库。它于 2015 年首次进入前端世界,由 Dan Abramov 和 Andrew Clark 构建,是革命性的状态管理解决方案。

在 React、Angular 或 Vue 等前端框架中,每个组件内部都管理着自己的状态。随着应用变得越来越复杂,跨多个组件管理状态变得繁琐而困难。Redux 正是解决这个问题的解决方案。

Redux 的工作原理是提供一个集中式的“store”,用于保存应用内的所有状态。应用中的每个组件都可以访问这个 store,而无需在组件树中传递 props。

redux-store.png
图片来自codecentric

Redux 流程

典型的 Redux 流程如下:

  1. 用户与视图交互以触发状态更新
  2. 当需要更新状态时,View 会发出一个动作
  3. Reducer 从调度器接收 action,并根据 action 描述的内容更新 Store 中的状态
  4. View 订阅了 Store 来监听状态变化。这些变化通过订阅方法通知 View,View 会相应地更新 UI。

redux-flow.png
图片来自ESRI

Redux 流程由三个主要组件组成:Action、Reducers 和 Store。理解这些组件之间的关系对于理解 Redux 的工作原理至关重要。

动作是具有必需type属性的 JavaScript 对象,并且可以在需要时包含自定义属性。它们仅用于描述状态发生了什么,并不负责更改状态。以下是一些动作示例:

//action to add a todo item
{ type: 'ADD_TODO', text: 'This is a new todo' } 
//action that pass a login payload
{ type: 'LOGIN', payload: { username: 'foo', password: 'bar' }} 
Enter fullscreen mode Exit fullscreen mode

动作type的 只是一个描述动作的字符串,添加的属性是更新状态所需的信息。动作通过store.dispatch(action)方法调度,然后由 Reducer 处理状态的更新。

Reducer是纯函数,它接收状态的当前值,按照 Action 的指示对其进行操作,然后输出状态的新值。Reducer 负责更改状态的值。以下是 Reducer 函数的一个简单示例:

//takes in the current state and action
//updates the value based on the action's type
function counterReducer(state = { value: 0 }, action) {
  switch (action.type) {
    case 'INCREASE':
      return { value: state.value + 1 }
    case 'DECREASE':
      return { value: state.value - 1 }
    default:
      return state
  }
}
Enter fullscreen mode Exit fullscreen mode

最后,状态将在 Store 中更新。Store管理所有状态的地方。只需一行代码即可创建:

const store = createStore(myComponent);
Enter fullscreen mode Exit fullscreen mode

组件必须订阅 Store 来监听状态更新,以便在 UI 中正确呈现状态。该store.subscribe()方法添加了一个更改监听器,每当 action 被调度时,该监听器都会被调用。

为什么选择 Redux Toolkit

至此,我们明白了为什么 Redux 成为状态管理的热门选择。它的模式使得状态可预测,因为 Reducer 是纯函数,这意味着传递的相同状态和 Action 总是会产生相同的输出。

由于 Redux 流程中每个部分的行为和工作方式都经过了严格的组织,因此它也易于维护和扩展。此外,Redux 还带来了许多其他好处,例如高效的测试、轻松的调试和更佳的性能。

然而,这个灵活且高级的状态管理库面临着一些挑战:

  1. 需要太多代码来将 Store 配置为优化级别/最佳实践
  2. 过多的样板代码会使代码不够干净和高效。
  3. 构建可扩展应用程序需要安装太多软件包
  4. 在大型应用程序中编写操作和减速器变得更加复杂和繁琐

为了应对这些挑战,Redux 团队推出了 Redux Toolkit,这是官方推荐的编写 Redux 逻辑的方法。它旨在通过将 Redux Core 与他们认为构建 Redux 应用所必需的软件包相结合,来加快 Redux 的开发速度。它是 Redux 的衍生产品,为 Redux 初学者或想要简洁、快速、干净的 Redux 代码的开发人员提供了许多最佳实践配置。

因此,让我们开始使用 Redux Toolkit 并使用新的 React 应用程序进行设置。

Redux Toolkit 入门

步骤 1:安装软件包

要开始使用 Redux Toolkit 和 React-Redux 包,您可以在现有的 React 应用上运行以下命令:

npm install @reduxjs/toolkit react-redux
Enter fullscreen mode Exit fullscreen mode

或者,通过 Create React App 安装:

npx create-react-app my-app --template redux
Enter fullscreen mode Exit fullscreen mode

步骤2:创建并初始化商店

现在让我们创建一个 store 来保存我们的状态。我们可以在文件夹store.js中创建一个文件src,并在其中添加以下代码:

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: {} //add reducers here
})
Enter fullscreen mode Exit fullscreen mode

此处的 替换了Redux 中的configureStore原有。与 不同Redux Toolkit 中的 不仅可以创建 store,还可以接受 reducer 函数作为参数,并自动设置 Redux DevTools Extension 以便于调试。createStorecreateStoreconfigureStore

步骤 3:在 React 应用中提供 Store

一旦我们的商店创建完成,我们就需要让 React 应用中的每个组件都能够访问它。我们可以使用Provider之前react-redux安装的包中的 来实现这一点。

在我们的index.js文件中,我们像这样导入Provider和我们的store.js

import store from './store'
import { Provider } from 'react-redux'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)
Enter fullscreen mode Exit fullscreen mode

步骤 4:编写 Reducer 和 Action

我们现在可以为我们的 Redux 存储编写一些 reducer 函数和操作。

在传统的 Redux 中,我们通常会分别编写 Reducer 和 Action。例如,一个计数器应用的简单 Reducer 和 Action 在传统的 Redux 中会像这样编写:

行动

// actions/index.js
export const Increase = () => ({
  type: 'INCREASE'
})

export const Decrease = () => ({
  type: 'DECREASE'
})
Enter fullscreen mode Exit fullscreen mode

Reducers

// reducers/index.js
export default (state = 0, action) => {
  switch (action.type) {
    case 'INCREASE':
      return state + 1
    case 'DECREASE':
      return state - 1
    default:
      return state
  }
}
Enter fullscreen mode Exit fullscreen mode

使用 Redux Toolkit,我们可以通过使用 使代码更加简洁。在应用程序的文件夹createSlice创建一个文件。Reducer 和 Action 都可以像这样写在切片下:counterSlice.jssrc

import { createSlice } from '@reduxjs/toolkit'

export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    increase: state => {
      state.value += 1
    },
    decrease: state => {
      state.value -= 1
    }
  }
})

// each case under reducers becomes an action
export const { increase, decrease } = counterSlice.actions

export default counterSlice.reducer
Enter fullscreen mode Exit fullscreen mode

从上面的代码可以看出,在 Redux Toolkit 中定义 Reducer 和 Action 变得更加简洁快捷。不再需要使用 switch 语句来管理 Action 及其对应的 Reducer。

你可能注意到的另一件事是,我们现在似乎直接在 Reducer 函数中修改了状态的值,而不是返回一个新值来更新状态。这实际上是因为 Redux Toolkit 使用了 Immer 库,它允许在 Reducer 中编写“修改”逻辑。

有关 Immer 如何工作的更多信息,请访问此处的文档。

步骤5:将 Reducer 导入到 Store

我们已经从 中导出了 Reducer 和 Actions counterSlice.js。接下来,让我们将 Reducer 导入到 中store.js

import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '.counterSlice' //import our reducer from step 4

export default configureStore({
  reducer: {
    counter: counterReducer //add our reducer from step 4
  }
})
Enter fullscreen mode Exit fullscreen mode

步骤 6:从 UI 调度操作

正如我们之前所了解的,我们的 View 会触发一个 action 来分发,以更新状态。在 Redux 中,我们使用store.dispatch(action)分发 action。

相反,让我们使用 React-Redux 来使用useDispatch钩子来分派动作并useSelector从存储中读取数据。

在我们的文件夹中创建一个Counter.js文件src来表示我们的 Counter 组件。在这个文件中,我们将从 React-Redux 导入我们的useDispatchuseSelectorhooks。我们还将从 导入我们的 action counterSlice.js

import { useSelector, useDispatch } from 'react-redux'
import { decrease, increase } from './counterSlice'
Enter fullscreen mode Exit fullscreen mode

然后,我们的 Counter 函数将初始化我们的 2 个钩子并返回dispatch(action)在点击时触发的 UI 元素。

export function Counter() {
  const count = useSelector(state => state.counter.value)
  // in our slice, we provided the name property as 'counter'
  // and the initialState with a 'value' property
  // thus to read our data, we need useSelector to return the state.counter.value

  const dispatch = useDispatch()
  // gets the dispatch function to dispatch our actions

  return (
    <div>
        <button onClick={() => dispatch(increase())}>
          Increase
        </button>
        <p>{count}<p>
        <button onClick={() => dispatch(decrease())}>
          Decrease
        </button>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

开源会话重播

在生产环境中调试Web 应用程序可能既困难又耗时。OpenReplay是 FullStory、LogRocket 和 Hotjar 的开源替代方案。它允许您监控和重放用户的所有操作,并显示您的应用在遇到每个问题时的表现。
这就像打开浏览器的检查器,同时监视用户的行为。OpenReplay
是目前唯一可用的开源替代方案。

开放重播

对于现代前端团队来说,快乐调试 -开始免费监控您的网络应用程序

结论

Redux Toolkit 对于初学者和想要减少 Redux 样板代码的开发者来说都是一个不错的选择。它使我们能够编写更简洁、更易读的代码,同时保持 Redux 的流程和模式。

感谢您的阅读。希望本文能帮助您理解 Redux 并在应用程序中使用 Redux Toolkit。谢谢!

文章来源:https://dev.to/asayerio_techblog/redux-is-dead-long-live-redux-toolkit-db8
PREV
Laravel Docker Docker 对于本地 Laravel 开发的优势
NEXT
Redux 死了吗?