Skip to main content

Redux 入门

Redux 是一个用于可预测和可维护的全局状态管理的 JS 库。

¥Redux is a JS library for predictable and maintainable global state management.

它可以帮助你编写行为一致、在不同环境(客户端、服务器和原生)中运行并且易于测试的应用。最重要的是,它提供了出色的开发者体验,例如 实时代码编辑与时间旅行调试器相结合

¥It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. On top of that, it provides a great developer experience, such as live code editing combined with a time traveling debugger.

你可以将 Redux 与 React 或任何其他视图库一起使用。它很小(2kB,包括依赖),但拥有一个庞大的可用插件生态系统。

¥You can use Redux together with React, or with any other view library. It is tiny (2kB, including dependencies), but has a large ecosystem of addons available.

Redux 工具包 是我们官方推荐的编写 Redux 逻辑的方法。它围绕 Redux 核心,并包含我们认为构建 Redux 应用所必需的包和函数。Redux Toolkit 构建了我们建议的最佳实践,简化了大多数 Redux 任务,防止常见错误,并使编写 Redux 应用变得更加容易。

¥Redux Toolkit is our official recommended approach for writing Redux logic. It wraps around the Redux core, and contains packages and functions that we think are essential for building a Redux app. Redux Toolkit builds in our suggested best practices, simplifies most Redux tasks, prevents common mistakes, and makes it easier to write Redux applications.

RTK 包含有助于简化许多常见用例的实用程序,包括 存储设置创建 reducer 并编写不可变的更新逻辑 甚至 立即创建整个 "切片" 状态

¥RTK includes utilities that help simplify many common use cases, including store setup, creating reducers and writing immutable update logic, and even creating entire "slices" of state at once.

无论你是设置第一个项目的全新 Redux 用户,还是想要简化现有应用的经验丰富的用户,Redux 工具包 都可以帮助你改进 Redux 代码。

¥Whether you're a brand new Redux user setting up your first project, or an experienced user who wants to simplify an existing application, Redux Toolkit can help you make your Redux code better.

安装

¥Installation

Redux 工具包

¥Redux Toolkit

Redux Toolkit 在 NPM 上作为包提供,可与模块打包器或 Node 应用一起使用:

¥Redux Toolkit is available as a package on NPM for use with a module bundler or in a Node application:

# NPM
npm install @reduxjs/toolkit

# Yarn
yarn add @reduxjs/toolkit

创建 React Redux 应用

¥Create a React Redux App

使用 React 和 Redux 启动新应用的推荐方法是使用 我们的 Vite 官方 Redux+TS 模板,或使用 Next 的 with-redux 模板 创建新的 Next.js 项目。

¥The recommended way to start new apps with React and Redux is by using our official Redux+TS template for Vite, or by creating a new Next.js project using Next's with-redux template.

这两个工具都已经为该构建工具适当配置了 Redux Toolkit 和 React-Redux,并附带了一个小示例应用,演示如何使用 Redux Toolkit 的多个功能。

¥Both of these already have Redux Toolkit and React-Redux configured appropriately for that build tool, and come with a small example app that demonstrates how to use several of Redux Toolkit's features.

# Vite with our Redux+TS template
# (using the `degit` tool to clone and extract the template)
npx degit reduxjs/redux-templates/packages/vite-template-redux my-app

# Next.js using the `with-redux` template
npx create-next-app --example with-redux my-app

我们目前没有官方的 React Native 模板,但建议将这些模板用于标准 React Native 和 Expo:

¥We do not currently have official React Native templates, but recommend these templates for standard React Native and for Expo:

Redux 核心

¥Redux Core

Redux 核心库在 NPM 上作为包提供,可与模块打包器或 Node 应用一起使用:

¥The Redux core library is available as a package on NPM for use with a module bundler or in a Node application:

# NPM
npm install redux

# Yarn
yarn add redux

该软件包包含预编译的 ESM 版本,可以直接在浏览器中用作 <script type="module"> 标签

¥The package includes a precompiled ESM build that can be used as a <script type="module"> tag directly in the browser.

欲了解更多详情,请参阅 安装 页。

¥For more details, see the Installation page.

基本示例

¥Basic Example

应用的整个全局状态存储在单个存储内的对象树中。更改状态树的唯一方法是创建一个操作(一个描述发生情况的对象)并将其分派到存储。要指定如何更新状态以响应操作,你可以编写纯 reducer 函数,根据旧状态和操作计算新状态。

¥The whole global state of your app is stored in an object tree inside a single store. The only way to change the state tree is to create an action, an object describing what happened, and dispatch it to the store. To specify how state gets updated in response to an action, you write pure reducer functions that calculate a new state based on the old state and the action.

Redux Toolkit 简化了编写 Redux 逻辑和设置存储的过程。使用 Redux Toolkit,基本的应用逻辑如下所示:

¥Redux Toolkit simplifies the process of writing Redux logic and setting up the store. With Redux Toolkit, the basic app logic looks like:

import { createSlice, configureStore } from '@reduxjs/toolkit'

const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
incremented: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decremented: state => {
state.value -= 1
}
}
})

export const { incremented, decremented } = counterSlice.actions

const store = configureStore({
reducer: counterSlice.reducer
})

// Can still subscribe to the store
store.subscribe(() => console.log(store.getState()))

// Still pass action objects to `dispatch`, but they're created for us
store.dispatch(incremented())
// {value: 1}
store.dispatch(incremented())
// {value: 2}
store.dispatch(decremented())
// {value: 1}

你不是直接改变状态,而是使用称为操作的普通对象来指定想要发生的改变。然后,你编写一个称为“reducer”的特殊函数来决定每个操作如何转换整个应用的状态。

¥Instead of mutating the state directly, you specify the mutations you want to happen with plain objects called actions. Then you write a special function called a reducer to decide how every action transforms the entire application's state.

在典型的 Redux 应用中,只有一个具有单个根 reducer 功能的存储。随着应用的增长,你将根 reducer 拆分为更小的 reducer,独立地在状态树的不同部分上运行。这就像 React 应用中只有一个根组件一样,但它是由许多小组件组成的。

¥In a typical Redux app, there is just a single store with a single root reducer function. As your app grows, you split the root reducer into smaller reducers independently operating on the different parts of the state tree. This is exactly like how there is just one root component in a React app, but it is composed out of many small components.

对于计数器应用来说,这种架构可能看起来很多,但这种模式的美妙之处在于它可以很好地扩展到大型和复杂的应用。它还支持非常强大的开发工具,因为可以跟踪每个突变到导致它的操作。你可以记录用户会话并通过重播每个操作来重现它们。

¥This architecture might seem like a lot for a counter app, but the beauty of this pattern is how well it scales to large and complex apps. It also enables very powerful developer tools, because it is possible to trace every mutation to the action that caused it. You can record user sessions and reproduce them just by replaying every action.

Redux Toolkit 允许我们编写更短、更易于阅读的逻辑,同时仍然遵循相同的 Redux 行为和数据流。

¥Redux Toolkit allows us to write shorter logic that's easier to read, while still following the same Redux behavior and data flow.

旧版示例

¥Legacy Example

为了进行比较,原始的 Redux 旧版语法(没有抽象)如下所示:

¥For comparison, the original Redux legacy syntax (with no abstractions) looks like this:

import { createStore } from 'redux'

/**

* This is a reducer - a function that takes a current state value and an

* action object describing "what happened", and returns a new state value.

* A reducer's function signature is: (state, action) => newState

* * The Redux state should contain only plain JS objects, arrays, and primitives.

* The root state value is usually an object. It's important that you should

* not mutate the state object, but return a new object if the state changes.

* * You can use any conditional logic you want in a reducer. In this example,

* we use a switch statement, but it's not required.
*/
function counterReducer(state = { value: 0 }, action) {
switch (action.type) {
case 'counter/incremented':
return { value: state.value + 1 }
case 'counter/decremented':
return { value: state.value - 1 }
default:
return state
}
}

// Create a Redux store holding the state of your app.
// Its API is { subscribe, dispatch, getState }.
let store = createStore(counterReducer)

// You can use subscribe() to update the UI in response to state changes.
// Normally you'd use a view binding library (e.g. React Redux) rather than subscribe() directly.
// There may be additional use cases where it's helpful to subscribe as well.

store.subscribe(() => console.log(store.getState()))

// The only way to mutate the internal state is to dispatch an action.
// The actions can be serialized, logged or stored and later replayed.
store.dispatch({ type: 'counter/incremented' })
// {value: 1}
store.dispatch({ type: 'counter/incremented' })
// {value: 2}
store.dispatch({ type: 'counter/decremented' })
// {value: 1}

学习 Redux

¥Learn Redux

我们有各种资源可以帮助你学习 Redux。

¥We have a variety of resources available to help you learn Redux.

Redux 概要教程

¥Redux Essentials Tutorial

Redux 概要教程 是 "自上而下" 的教程,使用我们最新推荐的 API 和最佳实践来教授 "如何正确使用 Redux"。我们建议从那里开始。

¥The Redux Essentials tutorial is a "top-down" tutorial that teaches "how to use Redux the right way", using our latest recommended APIs and best practices. We recommend starting there.

Redux 基础教程

¥Redux Fundamentals Tutorial

Redux 基础教程 是 "自下而上" 的教程,从第一原理讲授 "Redux 是如何工作的",没有任何抽象,以及为什么存在标准 Redux 使用模式。

¥The Redux Fundamentals tutorial is a "bottom-up" tutorial that teaches "how Redux works" from first principles and without any abstractions, and why standard Redux usage patterns exist.

学习 Modern Redux 直播

¥Learn Modern Redux Livestream

Redux 维护者 Mark Erikson 出现在 "和杰森一起学习" 节目中,解释了我们今天如何建议使用 Redux。该节目包括一个实时编码的示例应用,展示了如何将 Redux Toolkit 和 React-Redux hooks 与 TypeScript 结合使用,以及新的 RTK 查询数据获取 API。

¥Redux maintainer Mark Erikson appeared on the "Learn with Jason" show to explain how we recommend using Redux today. The show includes a live-coded example app that shows how to use Redux Toolkit and React-Redux hooks with TypeScript, as well as the new RTK Query data fetching APIs.

请参阅 "学习现代 Redux" 节目注意页面 以获取脚本和示例应用源的链接。

¥See the "Learn Modern Redux" show notes page for a transcript and links to the example app source.

¥

附加教程

¥Additional Tutorials

其他资源

¥Other Resources

帮助和讨论

¥Help and Discussion

Reactiflux Discord 社区#redux 通道 是我们的官方资源,可解答与学习和使用 Redux 相关的所有问题。Reactiflux 是一个闲逛、提问和学习的好地方 - 来加入我们吧!

¥The #redux channel of the Reactiflux Discord community is our official resource for all questions related to learning and using Redux. Reactiflux is a great place to hang out, ask questions, and learn - come join us!

你还可以使用 #redux 标签 询问有关 Stack Overflow 的问题。

¥You can also ask questions on Stack Overflow using the #redux tag.

如果你有错误报告或需要留下其他反馈,请在 Github 存储库上提出问题

¥If you have a bug report or need to leave other feedback, please file an issue on the Github repo

你应该使用 Redux 吗?

¥Should You Use Redux?

Redux 是组织状态的宝贵工具,但你还应该考虑它是否适合你的情况。不要仅仅因为有人说你应该使用 Redux - 花一些时间来了解使用它的潜在好处和权衡。

¥Redux is a valuable tool for organizing your state, but you should also consider whether it's appropriate for your situation. Don't use Redux just because someone said you should - take some time to understand the potential benefits and tradeoffs of using it.

以下是关于何时使用 Redux 有意义的一些建议:

¥Here are some suggestions on when it makes sense to use Redux:

  • 随着时间的推移,你拥有合理数量的数据变化

    ¥You have reasonable amounts of data changing over time

  • 你的状态需要单一的事实来源

    ¥You need a single source of truth for your state

  • 你发现将所有状态保留在顶层组件中已经不够了

    ¥You find that keeping all your state in a top-level component is no longer sufficient

有关如何使用 Redux 的更多想法,请参阅:

¥For more thoughts on how Redux is meant to be used, see: