Skip to main content

核心概念

¥Core Concepts

想象一下你的应用的状态被描述为一个普通对象。例如,待办事项应用的状态可能如下所示:

¥Imagine your app’s state is described as a plain object. For example, the state of a todo app might look like this:

{
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}

这个对象就像一个“模型”,只是没有设置器。这样代码的不同部分就不能随意改变状态,从而导致难以重现的错误。

¥This object is like a “model” except that there are no setters. This is so that different parts of the code can’t change the state arbitrarily, causing hard-to-reproduce bugs.

要更改状态中的某些内容,你需要调度一个操作。动作是一个简单的 JavaScript 对象(注意我们没有引入任何魔法?),它描述了发生的事情。以下是一些示例操作:

¥To change something in the state, you need to dispatch an action. An action is a plain JavaScript object (notice how we don’t introduce any magic?) that describes what happened. Here are a few example actions:

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

强制将每项更改都描述为一个操作,可以让我们清楚地了解应用中发生的情况。如果事情发生了变化,我们知道为什么会发生变化。行动就像已发生事件的面包屑。最后,为了将状态和操作联系在一起,我们编写了一个称为“reducer”的函数。再说一次,它没有什么神奇之处 - 它只是一个以状态和操作作为参数的函数,并返回应用的下一个状态。为大型应用编写这样的函数是很困难的,因此我们编写了管理部分状态的较小函数:

¥Enforcing that every change is described as an action lets us have a clear understanding of what’s going on in the app. If something changed, we know why it changed. Actions are like breadcrumbs of what has happened. Finally, to tie state and actions together, we write a function called a reducer. Again, nothing magical about it — it’s just a function that takes state and action as arguments, and returns the next state of the app. It would be hard to write such a function for a big app, so we write smaller functions managing parts of the state:

function visibilityFilter(state = 'SHOW_ALL', action) {
if (action.type === 'SET_VISIBILITY_FILTER') {
return action.filter
} else {
return state
}
}

function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([{ text: action.text, completed: false }])
case 'TOGGLE_TODO':
return state.map((todo, index) =>
action.index === index
? { text: todo.text, completed: !todo.completed }
: todo
)
default:
return state
}
}

我们编写另一个 reducer,通过为相应的状态键调用这两个 reducer 来管理应用的完整状态:

¥And we write another reducer that manages the complete state of our app by calling those two reducers for the corresponding state keys:

function todoApp(state = {}, action) {
return {
todos: todos(state.todos, action),
visibilityFilter: visibilityFilter(state.visibilityFilter, action)
}
}

这基本上就是 Redux 的全部思想。请注意,我们没有使用任何 Redux API。它附带了一些实用程序来促进这种模式,但主要思想是描述状态如何随着时间的推移更新以响应操作对象,并且你编写的 90% 的代码只是纯 JavaScript,没有使用 Redux 本身、其 API 或任何魔法。

¥This is basically the whole idea of Redux. Note that we haven’t used any Redux APIs. It comes with a few utilities to facilitate this pattern, but the main idea is that you describe how your state is updated over time in response to action objects, and 90% of the code you write is just plain JavaScript, with no use of Redux itself, its APIs, or any magic.