理解 redux

Redux是一个独立的状态管理架构,常用于React应用。它包含action、reducer和store三个要素。action描述状态变化,reducer处理action并返回新状态,store则管理状态和reducer。开发者需要定义action和reducer,然后通过createStore创建store。store提供了dispatch和getState等方法来执行和获取状态。reducer必须是纯函数,不能直接调用,且不能有副作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redux是当下流行的web前端所使用的一个状态管理架构。它本身是一个独立的构造,没有与任何其它库的耦合。由于reactjs的流行, 它自然而然的成为了react状态管理的延伸架构。 本文不打算讨论redux的优点以及细节, 只是想从纯粹的设计角度去理解redux状态管理的模式。

概览

redux把状态管理抽象成3个要素, action, reducer, store。

action是状态变化的描述性数据结构, 即一个标签(type)来标识action的名字, 和相关的数据

    {
        type: "添加订单",
        text: "Eat meal"
    }

reducer是action的handler, 是一个函数来具体执行状态变化操作.

store是状态对象和reducer的管理器, 在使用redux的时候, 你不应该直接执行reducer, 这破坏了它的设计意图。你要把它放到store中, 通过store去执行(dispatch)状态变化操作, 你也要通过store来获取状态对象。

更具体的描述:

  1. action, 描述发生了什么的对象, action是store的唯一信息来源, 通过store.dispatch(action)产生,
    而dispatch就是去调用reducer更新状态, 在store内部, currentState维持应用程序的当前状态:

    currentState = currentReducer(currentState, action)
    

    一个action的结构:

    {
        type: "ADD_TODO",
        text: "Eat meal"
    }
    
  2. reducer, 完成action具体的操作: (oldState, action)=>newState, 也就是handling action.

    写reducer时要求有初始化逻辑, 也就是如果state是undefined要给state赋值. 另外如果action未知时必须返回函数的state参数, 也就是旧的state.

    function todos(state, action) {
      if (state === undefined) state = [];
      switch (action.type) {
        case 
        ....
        default:
          return state;
      }
    }
    
  3. store负责把action和reducer结合起来, store 有以下特性:

    • 获得状态 getState()
    • 更新状态 dispatch(action)
    • 登记监听器 subscribe(listener)

    store的建立需要通过redux的函数createStore,把reducer传入store, createStore函数的签名是这样:

    createStore(reducer, initialState)
    

    注意initialState永远不用赋值, 所以总是undefined, 这正好被用在reducer函数参数中来做初始化

有了以上设施, 整个流程就是先定义action, 然后是定义action handler也就是reducer, 然后把reducer传给createStore建立store:

store = createStore(reducer)

在运行createStore时会初始化state, 也就是它内部做一次dispatch,

...
// 默认action
export var ActionTypes = {
  INIT: '@@redux/INIT'
}
currentState = initialState // 默认是undefined,传给reducer做初始化
currentReducer = reducer
...
dispatch({ type: ActionTypes.INIT }) 
... 

如果看dispatch函数, 他基本上就是去调用reducer,

currentState = currentReducer(currentState, action)

在初始化的dispatch时, action的值为 '@@redux/INIT', currentState为undefined

根据2的描述, 调用store=createStore(reducer)后, reducer返回的初始化状态对象被保存在store的currentState中, 通过store.getState()获取.

createStore建立后, store就成为调用reducer的代理, 通过store.getState()得到currentState, 通过store.dispatch(ACTION)再次调用reducer更新currentState.

总结

redux架构基于以下的约定构造:

  1. 函数reducer操作状态, 它的返回值构成了状态对象以及该对象的变化。但reducer不应该被直接调用, 状态对象被另一个独立的对象store(状态管理器)来维护. 在建立管理器时把reducer作为参数传递, 使得管理器可以调用它. 管理器通过暴露dispatch方法来调用reducer自身以改变状态, 同时状态对象(reducer的返回值)被封装在管理器中, 通过管理器暴露的方法getState获取.

  2. 状态信息被独立描述在action中, reducer的状态变化处理逻辑需要使用它. 它的结构包括变化类型(action.type), 以及变化的数据. reducer作为变化的具体处理者依据action的信息操作状态并返回新的状态

  3. reducer和action都由架构使用者定义和编码, redux提供的是管理器: 通过store=createStore(reducer)初始化状态对象, 通过store的其它方法来改变和获取状态. 而架构使用者只调用store方法来请求对状态的处理.

  4. 架构使用者在编码reducer时, 除了前述的约定以外, 还必须保证reducer是没有副作用的:

    a. 不允许直接改变state的值,只允许生成新的值

    b. 不应该有对外的API调用或者路由变化, 这些都应该在调用action前操作.

  5. 根(root) reducer,这个概念就是合并多个reducer, 形成一个单一的数据结构, 如:

    reducers:

    function visibilityFilter(state = VisibilityFilters.SHOW_ALL, action) {
      switch (action.type) {
        case 
        ...
        default:
          return state
      }
    }
    
    function todos(state = [], action) {
      switch (action.type) {
        case 
        ...
        default:
          return state
      }
    }
    

    root reducer:

    / * 
    合并reducer其实就是合并数据结构,将reducer函数的返回值包装在一个结构里.
    根reducer通过将其它reducer的调用返回值包装在一起, 形成一个完整的状态数据对象结构.
    */
    
    export default function todoApp(state = {}, action) {     
      // 在store.dispatch时, 下面的reducer函数将依次被调用, 
      // 当一个传递给reducer的action参数不在switch里时, default会直接返回state参数, 见前述reducer代码
      return {
        vsfilter: visibilityFilter(state.vsfilter, action),
        tdlist: todos(state.tdlist, action)
      }
    }
    

    最后, 应该传递给createStore的是这个根reducer:

    store = createStore(todoApp)
    

redux的核心代码(createStore)不过160行, 了解了核心部分其实就掌握了它的脉络。再去读官方文档就感觉清晰得多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值