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

createStore目的:返回新的staste
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源码

猜你喜欢

转载自blog.csdn.net/qq1498982270/article/details/88744387
今日推荐