useState最简实现

为了理解hooks原理,我们遵循React运行流程,实现一个最简useState hook。

考虑如下例子:

function App() {
  const [num1, updateNum1] = useState(1);
  const [num2, updateNum2] = useState(2);
  const [num3, updateNum3] = useState(3);

  return (
    <p
      onClick={() => {
        updateNum1((num) => num + 1);
        updateNum1((num) => num + 2);
        updateNum1((num) => num + 3);
        updateNum2((num) => num + 1);
        updateNum2((num) => num + 2);
      }}
    >
      {num1},{num2},{num3}
    </p>
  );
}

ClassComponent是有实例的而FunctionComponent是没有实例的,FunctionCompoent的状态保存在fiber结构中。每个FunctionComponent对应一个fiber,结构如下:

fiber = { stateNode: App };

FunctionComponent的状态信息也保存在fiber中,并且以单链表的形式串联在一起,比如例子中mount后的state信息:

fiber = {
 stateNode: App,
  memoizedState: {
    memoizedState: 1,
    next: {
      memoizedState: 2,
      next: {
        memoizedState: 3,
        next: null,
      },
    },
  },
};

num1 -> num2 -> num3

当点击p标签触发状态更新。每个state都维护一个更新队列,调用更新方法会把更新信息保存到相应的队列中,当所有的更新方法执行完才会触发更新。点击p标签后触发渲染前fiber结构如下:

fiber = {
  memoizedState: {
    memoizedState: 1,
    queue: {
      pending: {
        action: (num) => num + 1,
        next: {
          action: (num) => num + 2,
          next: {
            action: (num) => num + 3,
            next: ...,//指向第一个update形成循环链表
          },
        },
      },
    },
    next: {
      memoizedState: 2,
      queue: {
        pending: {
          action: (num) => num + 1,
          next: {
            action: (num) => num + 2,
            next: ...,//指向第一个update形成循环链表
          },
        },
      },
      next: {
        memoizedState: 3,
        queue: {
          pending: null,
        },
        next: null,
      },
    },
  },
};

num1对应的更新循环链表结构:update1 -> update2 -> update3 -> update1,num2对应的更新循环链表结构:update1 -> update2 -> update1,num3对应的更新循环链表结构:null

当所有更新信息都准备好,React会触发重新渲染,useState方法根据上次状态和对应更新链表信息计算最新的state。

参考

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。