Skip to content

Latest commit

 

History

History

dispatchAction

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
function dispatchAction(fiber, queue, action) {
  // 前俩参数是在执行setReducer时候就被bind上的
  // 第一个fiber表示当前这个函数组件
  // 第二个queue表示每次执行useReducer时候
  // 都会创建一个对应的独立的workInProgressHook
  // 每个workInProgressHook都有个queue
  // 比如:
  /*
    function DingTest() {
      let [xxx, setXXX] = useState('ding1') // 会产生一个xxx的workInProgressHook
      let [yyy, setYYY] = useState('ding2') // 会产生一个yyy的workInProgressHook
      let [zzz, setZZZ] = useState('ding3') // 会产生一个zzz的workInProgressHook
      ...
      // 做一些其他事
      ...
    }
  */
  // 第三个参数就是自己再执行setXXX时候传进来的那个参数了

  // 第一次执行setXXX时候是不会有alternate的 这点和setState一样
  let alternate = fiber.alternate

  if (fiber === currentlyRenderingFiber || !!alternate && alternate === currentlyRenderingFiber) {
    // 在函数组件中执行setXXXX之类的hook会进来这里
    // 一般来讲这里fiber和currentlyRenderingFiber是不相等的
    // 因为currentlyRenderingFiber会在resetHooks这个函数中被置为null
    // 不过如果在一个函数组件中直接执行了setXXX那就会进到这里
    // 比如:
    /*
      function Ding() {
        let [ding, setDing] = useState('ding')
        setDing('xxx') // 这里没有把setDing放在回调中 而是直接执行
        return (
          <div>{ding}</div>
        )
      }
    */
    // 像上面这种情况就会fiber === currentlyRenderingFiber
  } else {
    let currentTime = requestCurrentTime() // 这里得到的是到目前为止 react还能处理多少单位时间(1单位时间是10ms)
    let expirationTime = computeExpirationForFiber(currentTime, fiber)
    // 手动创建一个更新
    let update = {
      next: null,
      expirationTime,
      action
    }
    let last = queue.last
    if (!last) {
      // 如果queue上没有last的话 说明当前是第一个更新
      // 要做一条循环链表
      queue.first = update
      update.next = update
    } else {
      // 如果有last的话 就获取到第一个update
      // 然后改变链表中的next和last的指向
      // 这就是链表正常操作
      // let first = last.next
      let first = queue.first
      if (!!first) {
        update.next = first
      }
      last.next = update
    }
    queue.last = update
    // queue其实在最初次渲染的时候就被存放在每个对应的workInProgressHook上了
    // 所以在更新的时候会走一些更新的逻辑

    // 所以这个函数其实就是每次执行setXXX时给对应的更新创建一个update
    // 比如:
    /*
      function Ding() {
        let [ding, setDing] = useState('ding')
        handleClick = () => {
          setDing('ding1')
          setDing('ding2')
          setDing('ding3')
        } // 这里没有把setDing放在回调中 而是直接执行
        return (
          <div onClick={handleClick}>{ding}</div>
        )
      }
    */
    // 会给这个Ding对应的workInProgressHook上创建三个update
    // 并通过链表的形式链接起来
    scheduleWork(fiber, expirationTime)
  }
}