前端进阶-redux源码分析--dispatch如何更新store

createStore目的:createStore = (..arguments) => newState

  • 先来看creatStore部分源码
export default function createStore(reducer, preloadedState, enhancer) {
  
  let currentReducer = reducer 
  let currentState = preloadedState /
  let isDispatching = false 


  export {
    dispatch, // 暴露出dispatch方法
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
  
}


复制代码

creteStore函数暴露出 dispatch方法, 来用于更新state,所以能通过store取到dispatch, 下面来看看dispatch如何实现更新state的

  • dispatch方法
// 定义的dispatch方法
  function dispatch(action) {
    // 如果 action不是一个简单对象,抛出异常
    if (!isPlainObject(action)) {
      throw new Error(
        'Actions must be plain objects. ' +
        'Use custom middleware for async actions.'
      )
    }
    // action必须定义type类型,否则报错
    if (typeof action.type === 'undefined') {
      throw new Error(
        'Actions may not have an undefined "type" property. ' +
        'Have you misspelled a constant?'
      )
    }
    // reducer内部不允许再次调用dispatch,否则抛出异常
    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }
    try {
      isDispatching = true
       // 将dispatch的action传给currentReducer进而更新state
      currentState = currentReducer(currentState, action)
      
    } finally {
      isDispatching = false
    }

    const listeners = currentListeners = nextListeners
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }
    return action
  }

复制代码

从dispatch方法源码可知道,其实就dispatch的action传给了我们自己定义的reducer来处理,然后返回新的newState

  • getState方法
  getState = () => {
    return currentState
  }

复制代码

combineReducers 如何更新store的

  • reducerA.js
const reducerA = (state = [], action) => {
  switch (action.type) {
    case 'A':
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ]
   
    default:
      return state
  }
}

export default reducer


复制代码
  • reducerB.js
const reducerA = (state = [], action) => {
   case 'B':
      return state.map(todo =>
        (todo.id === action.id)
          ? {...todo, completed: !todo.completed}
          : todo
      )
      default:
        return state
  }
}

复制代码
  • index.js
import {Provider} from 'react-redux'
import stores from './combineReducer.js'
import {createStore} from 'redux'
const store = createStore(stores)

ReactDOM.render(
    <Provider store={store}> 
        <App/>
    </Provider>, 
    document.getElementById('root')
);

createStore(combineReducer)

复制代码

这个时候,dispatch(action)等价于下面

// 用的是复合后的reducer来处理action
currentState = combineReducer(currentState, action)

// 如果此时type=A
currentState = combineReducer(currentState, {type:A...})


复制代码

这个时候actio.type = A ,应该是由reducerA来处理,返回新的state 但是combineReducer是如何根据传入的action ,传给相应reducer来处理了?

看看combineReducer实现就知道了

  • combineReducer.js
import { combineReducers } from 'redux'
import reducerA form './reducerA'
import reducerB form './reducerB'

export const stores = combineReducers({reducerA,reducerB}) //等价于下面

export default function stores(state = {}, action) {
  return { // 最终返回一个对象,即newState
    reducerA: reducerA(state.reducerA, action), 
    reducerB: reducerB(state.reducerB, action),
  }
}


复制代码

所以,其实combineReducer将action传给每个reducer,然后每个reducer根据传入的action判断是否有符合的type,然后进而判断是否更新state

当然combineReducer远不止这么简单,他还会判断传入的reducer是否是一个纯函数,是否返回一个对象,如果不符合要求会抛出相应的警告

下一篇文章继续分析combineReducer源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值