Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Hooks 原理逻辑 #51

Open
1 task done
imfenghuang opened this issue Jul 3, 2024 · 0 comments
Open
1 task done

React Hooks 原理逻辑 #51

imfenghuang opened this issue Jul 3, 2024 · 0 comments

Comments

@imfenghuang
Copy link
Owner

imfenghuang commented Jul 3, 2024

基于 React 18.3.1

useState 初始化

React Hooks

useState 更新

  1. 渲染期间更新 - 暂不考虑
  2. 通过事件回调函数触发

示例:

const Foo = () => {
  const [a, setA] = useState(0);

  const handleClick = () => {
    setA(1);
    setA(2);
    setA(1);
  };
  
  return <div onClick={handleClick} >{a}</div>
}

首次渲染完毕后,点击触发 handleClick,React 内部调用 dispatchSetState,创建 hook 的 update(每调一次 dispatchSetState,都会新建一个 update,有属性 actionnextaction 就是实际业务传入的数据)。

创建完毕后,进一步调用 enqueueConcurrentHookUpdate(fiber, queue, update, lane),把 updatequeue 更新到内部全局变量 concurrentQueues 上,会先判断 queue.interleaved 是否已经存在,如果不存在,则当前 update 创建循环链表,并将 update 赋值给 queue.interleavedqueue.interleaved = update;),同时把 queue 推入到 concurrentQueues 数组中。

之后,触发新的调度 scheduleUpdateOnFiber(TODO 调度逻辑)

在新的渲染开启前,会执行 finishQueueingConcurrentUpdates,将存储 concurrentQueues 里的 queue 数据进行处理,即把 queue.interleaved 里的循环链表迁移到 queue.pending 里,供后续使用。

重新执行函数组件时,useState 内部指向 updateState,实际调用 updateReducer(basicStateReducer, (initialState: any));,在 updateReducer 内部,调用 updateWorkInProgressHook,更新和获取 workInProgressHook,此时,这个 hook 对应的 queuehook.queue) 就是先前全部变量 concurrentQueues 更新之后的 queue。也就能正常获取 queue.pending,来计算最新的 state 值,并将新值更新到 hook.memoizedStatehook.baseStatehook.baseQueue 上。

// dispatchSetState 入参
function dispatchSetState<S, A>(
  fiber: Fiber,
  queue: UpdateQueue<S, A>, 
  action: A, // 在业务中调用时,传入的参数,如例子中的 1
)

// update 格式
const update: Update<S, A> = {
  lane,
  action,
  hasEagerState: false,
  eagerState: null,
  next: null,
};

// enqueueConcurrentHookUpdateAndEagerlyBailout
function enqueueConcurrentHookUpdateAndEagerlyBailout<S, A>(
  fiber: Fiber,
  queue: HookQueue<S, A>,
  update: HookUpdate<S, A>,
  lane: Lane,
): void {
  const interleaved = queue.interleaved;
  if (interleaved === null) {
    // 创建循环队列
    update.next = update;
    // 存到全局变量 concurrentQueues 上
    pushConcurrentUpdateQueue(queue);
  } else {
    update.next = interleaved.next;
    interleaved.next = update;
  }
  queue.interleaved = update;
}

// updateState
function updateState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
  return updateReducer(basicStateReducer, (initialState: any));
}

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant