商店
商店保存着您应用程序的整个 状态树。 改变其中状态的唯一方法是向它分发一个 动作,这将触发 根 reducer 函数 计算新的状态。
商店不是一个类。 它只是一个带有几个方法的对象。
要创建一个商店,将您的根 reducer 函数 传递给 Redux Toolkit 的 configureStore
方法,它将使用良好的默认配置设置一个 Redux 商店。(或者,如果您还没有使用 Redux Toolkit,您可以使用原始的 createStore
方法,但我们建议您尽快 迁移您的代码以使用 Redux Toolkit)
商店方法
getState()
返回您应用程序的当前状态树。 它等于商店的 reducer 最后返回的值。
返回值
(any): 您应用程序的当前状态树。
dispatch(action)
分发一个 action。这是触发状态改变的唯一方式。
商店的 reducer 函数将使用当前的 getState()
结果和给定的 action
同步调用。它的返回值将被视为下一个状态。它将从现在开始从 getState()
返回,并且更改监听器将立即被通知。
如果你试图从 reducer 内部调用 dispatch
,它将抛出一个错误,提示 "Reducers may not dispatch actions." Reducers 是纯函数 - 它们只能返回一个新的状态值,并且不能有副作用(而分发是一个副作用)。
在 Redux 中,订阅在根 reducer 返回新状态后被调用,因此你可以在订阅监听器中分发。你只被禁止在 reducer 内部分发,因为它们不能有副作用。如果你想对一个 action 产生副作用,正确的地方是在潜在的异步 action creator 中。
参数
action
(Object†): 一个描述对你的应用程序有意义的更改的普通对象。Action 是将数据放入商店的唯一方式,因此任何数据,无论是来自 UI 事件、网络回调还是其他来源(如 WebSockets),最终都需要作为 action 分发。Action 必须有一个type
字段,用于指示正在执行的 action 类型。类型可以定义为常量,并从另一个模块导入。最好使用字符串作为type
,而不是 Symbols,因为字符串是可序列化的。除了type
之外,action 对象的结构实际上取决于你。如果你感兴趣,可以查看 Flux Standard Action,了解如何构建 action 的建议。
返回值
(Object†): 派发的动作(参见注释)。
注释
† 通过调用 [`createStore`](/api/createstore) 获取的“普通”存储实现仅支持普通对象动作,并立即将它们传递给 reducer。但是,如果您使用 applyMiddleware
包装 createStore
,中间件可以以不同的方式解释动作,并提供对分派 异步动作 的支持。异步动作通常是异步原语,如 Promise、Observable 或 thunk。
中间件由社区创建,默认情况下不与 Redux 一起提供。您需要显式安装诸如 redux-thunk 或 redux-promise 之类的包才能使用它。您也可以创建自己的中间件。
要了解如何描述异步 API 调用,在动作创建者中读取当前状态,执行副作用,或将它们链接起来以按顺序执行,请参阅 applyMiddleware
的示例。
示例
import { createStore } from 'redux'
const store = createStore(todos, ['Use Redux'])
function addTodo(text) {
return {
type: 'ADD_TODO',
text
}
}
store.dispatch(addTodo('Read the docs'))
store.dispatch(addTodo('Read about the middleware'))
subscribe(listener)
添加一个更改监听器。每当分派动作时,它都会被调用,并且状态树的某些部分可能已发生更改。然后,您可以在回调中调用 getState()
来读取当前状态树。
您可以在更改监听器中调用 dispatch()
,但有以下注意事项
监听器应仅在响应用户操作或在特定条件下(例如,当存储具有特定字段时分派动作)调用
dispatch()
。在没有任何条件的情况下调用dispatch()
在技术上是可能的,但会导致无限循环,因为每次dispatch()
调用通常都会再次触发监听器。订阅在每次
dispatch()
调用之前被快照。如果您在调用监听器时订阅或取消订阅,这不会对当前正在进行的dispatch()
产生任何影响。但是,下一个dispatch()
调用(无论嵌套与否)都将使用订阅列表的最新快照。监听器不应该期望看到所有状态更改,因为状态可能在嵌套的
dispatch()
期间多次更新,然后才调用监听器。但是,可以保证在dispatch()
开始之前注册的所有订阅者将在其退出时使用最新状态被调用。
这是一个低级 API。大多数情况下,您不会直接使用它,而是会使用 React(或其他)绑定。如果您经常使用回调作为响应状态更改的钩子,您可能需要编写一个自定义的 observeStore
实用程序。Store
也是一个Observable
,因此您可以使用像RxJS这样的库来订阅更改。
要取消订阅更改监听器,请调用 subscribe
返回的函数。
参数
listener
(函数):每次分派操作且状态树可能已更改时要调用的回调。您可以在此回调中调用getState()
来读取当前状态树。可以合理地预期存储的 reducer 是一个纯函数,因此您可以比较状态树中某些深度路径的引用,以了解其值是否已更改。
返回值
(函数):取消订阅更改监听器的函数。
示例
function select(state) {
return state.some.deep.property
}
let currentValue
function handleChange() {
let previousValue = currentValue
currentValue = select(store.getState())
if (previousValue !== currentValue) {
console.log(
'Some deep nested property changed from',
previousValue,
'to',
currentValue
)
}
}
const unsubscribe = store.subscribe(handleChange)
unsubscribe()
replaceReducer(nextReducer)
替换存储当前用于计算状态的 reducer。
这是一个高级 API。如果您应用实施代码拆分,并且想要动态加载一些 reducer,您可能需要此 API。如果您为 Redux 实施热重载机制,您也可能需要此 API。
参数
nextReducer
(函数) 存储要使用的下一个 reducer。