Skip to content

Latest commit

 

History

History

useReducer

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
function useReducer(reducer, initialState, initialAction) {
  // 当在一个组件中连续调用多次useState时候
  // 每调用一次都会产生一个新的workInProgressHook
  // 但是会有个firstWorkInProgressHook上保存着每次创建的workInProgressHook这条链表
  workInProgressHook = createWorkInProgressHook()
  // 初次渲染时候这里的queue肯定是null
  // 而当执行了setXXX进入到这里时 queue上就有可能有值
  // queue上存储的就是执行setXXX时候传进来的update的那条链表
  let queue = workInProgressHook.queue

  if (!!queue) {
    if (isReRender) {
      // 一般在函数组件render阶段时调用了setXXX就有可能进入这里
    }

    let last = queue.last
    let first = queue.first
    let baseUpdate = workInProgressHook.baseUpdate
    if (!!baseUpdate) {

    }
    if (!!first) {
      let newState = workInProgressHook.baseState
      let newBaseState = null
      let newBaseUpdate = null
      let prevUpdate = baseUpdate
      let update = first
      // let didSkip = false
      do {
        // 每个更新和class组件更新一样 都有优先级
        let updateExpirationTime = update.expirationTime
        // renderExpirationTime 是在prepareToUseHooks方法中赋值的
        // 就是nextRenderExpirationTime
        if (updateExpirationTime < renderExpirationTime) {
          // 进入这里说明当前这个更新的优先级比较低 可以放到之后再更新
          // if (!didSkip) {
          //   // 这一小块在干嘛暂时不太理解它要干嘛
          //   // 应该是要记录下被跳过的更新的前一个更新和前一个state
          //   didSkip = true
          //   newBaseUpdate = prevUpdate
          //   newBaseState = newState
          // }
          // remainingExpirationTime是一个全局变量 只有这个useReducer中会给它赋值
          // 初始是NoWork
          if (updateExpirationTime > remainingExpirationTime) {
            // 进入这里说明当前这个更新可以暂时先被跳过
            // 同时将remainingExpirationTime这个全局变量
            // 赋值为所有被跳过的更新中优先级最高的那个
            remainingExpirationTime = updateExpirationTime
          }
        } else {
          // 进入这里说明当前update不能被跳过
          let action = update.action
          // 传进来的reducer就是下面这个方法
          // function basicStateReducer(state, action) {
          //   return typeof action === 'function' ? action(state) : action
          // }
          newState = reducer(newState, action)
          // 到这为止就已经生成了一个新的值了

          // 然后用当前update的next作为下一个要循环的update
          // 同时将当前这个update记录为上一个update
          prevUpdate = update
          update = update.next
        }
      } while (update !== null && update !== first)

      // if (!didSkip) {
      //   newBaseUpdate = prevUpdate
      //   newBaseState = newState
      // }
      newBaseUpdate = prevUpdate
      newBaseState = newState

      workInProgressHook.memoizedState = newState
      workInProgressHook.baseUpdate = newBaseUpdate
      workInProgressHook.baseState = newBaseState

      return [workInProgressHook.memoizedState, queue.dispatch]
    }
  }

  if (reducer === basicStateReducer) {
    // 在使用useState时候会内部调用useReducer
    // 然后会同时将basicStateReducer作为参数传进来
    // 所以暂时可以认为通过reducer和basicStateReducer是否相等来判断是否是执行的useState
    if (typeof initialState === 'function') {
      // 如果传进来的参数是个函数的话
      // 要获取到这个函数的返回值
      initialState = initialState()
    }
  } else {
    // 如果不是调用的useState进入到的这里的话
    // 那就像是一个正常的reducer使用那样
    // 有点类似于redux中的reducer
    initialState = reducer(initialState, initialAction)
  }
  workInProgressHook.memoizedState = initialState
  workInProgressHook.baseState = initialState
  queue = workInProgressHook.queue = {
    first: null,
    last: null,
    dispatch: null
  }
  queue.dispatch = dispatchAction.bind(null, currentlyRenderingFiber, queue)
  return [workInProgressHook.memoizedState, queue.dispatch]
}