浅谈React中 useState、useEffect源码解析

254 阅读2分钟

本文将对React的useState和useEffect的底层源码进行详细的解析,让我们更深入的了解这些技术的实现原理。

一、useState源码解析

1.1 核心函数

首先,我们来看一看useState的源码:

function useState<S>(initialState: (() => S) | S): [S, Dispatch<SetStateAction<S>>] {
  const dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}

可以看到,useState函数本身非常简单,它只是从resolveDispatcher中获取一个dispatcher,然后调用dispatcher.useState方法传入初始值。

1.2 resolveDispatcher函数

resolveDispatcher函数用于解析分发器,它定义如下:

let _dispatcher: Dispatcher | null = null;

function resolveDispatcher() {
  if (_dispatcher != null) {
    return _dispatcher;
  } else {
    // 创建一个新的Dispatcher
    const dispatcher = createDispatcher();
    _dispatcher = dispatcher;
    return dispatcher;
  }
}

从源码可以看出,resolveDispatcher函数会先检查一下_dispatcher是否为null,如果不是null,那么就直接返回_dispatcher;如果为null,那么就会通过createDispatcher函数创建一个新的Dispatcher,然后将该Dispatcher赋值给_dispatcher,最后再返回该dispatcher。

1.3 createDispatcher函数

createDispatcher函数主要用于创建一个新的Dispatcher:

function createDispatcher() {
  const currentHook = getCurrentHook();
  // ... 省略一些代码
  return {
    useState<S>(initialState: (() => S) | S): [S, Dispatch<SetStateAction<S>>] {
      const hook =
        currentHook != null
          ? currentHook
          : createHook(null, null, []);
      // ... 省略一些代码
      return stateHook;
    },
    // ... 省略其他代码
  };
}

从上面的源码可以看出,createDispatcher函数会先通过getCurrentHook获取当前的Hook,如果当前Hook不存在,那么就会创建一个新的Hook,然后使用该Hook创建一个新的useState Hook,最后返回该useState Hook,当我们调用useState时,就会执行该useState Hook。

二、useEffect源码解析

2.1 核心函数

首先,我们来看一看useEffect的源码:

function useEffect(
  create: () => (() => void) | void,
  deps: Array<mixed> | void | null,
): void {
  const dispatcher = resolveDispatcher();
  return dispatcher.useEffect(create, deps);
}

可以看到,useEffect函数与useState函数非常类似,它也只是从resolveDispatcher中获取一个dispatcher,然后调用dispatcher.useEffect传入create函数和deps参数。

2.2 resolveDispatcher函数

与useState类似,resolveDispatcher函数也用于解析分发器,它定义如下:

let _dispatcher: Dispatcher | null = null;

function resolveDispatcher() {
  if (_dispatcher != null) {
    return _dispatcher;
  } else {
    // 创建一个新的Dispatcher
    const dispatcher = createDispatcher();
    _dispatcher = dispatcher;
    return dispatcher;
  }
}

从源码可以看出,resolveDispatcher函数与useState类似,会先检查一下_dispatcher是否为null,如果不是null,那么就直接返回_dispatcher;如果为null,那么就会通过createDispatcher函数创建一个新的Dispatcher,然后将该Dispatcher赋值给_dispatcher,最后再返回该dispatcher。

2.3 createDispatcher函数

createDispatcher函数主要用于创建一个新的Dispatcher:

function createDispatcher() {
  const currentHook = getCurrentHook();
  // ... 省略一些代码
  return {
    useEffect(create: () => (() => void) | void, deps: Array<mixed> | void | null): void {
      const hook =
        currentHook != null
          ? currentHook
          : createHook(null, null, []);
      // ... 省略一些代码
      return effectHook;
    },
    // ... 省略其他代码
  };
}

从上面的源码可以看出,createDispatcher函数和useState函数也非常类似,它会先通过getCurrentHook获取当前的Hook,如果当前Hook不存在,那么就会创建一个新的Hook,然后使用该Hook创建一个新的useEffect Hook,最后返回该useEffect Hook。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情