React useState 源码分析

 关于useState的源码分析, 这也表明了为什么useState的使用几个点:
1. 组件最上方调用。

2. 尽量避免在if/for语句中调用。

import React from "react";
import ReactDOM from "react-dom";
// useState 源码中的链表实现
let firstWorkInProgressHook = { memoizedState: null, next: null };
let workInProgressHook;
function useState(initState) {
  let currentHook = workInProgressHook.next
    ? workInProgressHook.next
    : { memoizedState: initState, next: null };
  function setState(newState) {
    currentHook.memoizedState = newState;
    render();
  }
  // 这就是为什么 useState 书写顺序很重要的原因
  // 假如某个 useState 没有执行,会导致指针移动出错,数据存取出错
  if (workInProgressHook.next) {
    // 这里只有组件刷新的时候,才会进入
    // 根据书写顺序来取对应的值
    console.log(workInProgressHook);
    workInProgressHook = workInProgressHook.next;
  } else {
    // 只有在组件初始化加载时,才会进入
    // 根据书写顺序,存储对应的数据
    // 将 firstWorkInProgressHook 变成一个链表结构
    workInProgressHook.next = currentHook;
    // 将 workInProgressHook 指向 {memoizedState: initState, next: null}
    workInProgressHook = currentHook;
    console.log("firstWorkInProgressHook", firstWorkInProgressHook);
  }
  return [currentHook.memoizedState, setState];
}
function Counter() {
  // 每次组件重新渲染的时候,这里的 useState 都会重新执行
  const [name, setName] = useState("计数器");
  const [number, setNumber] = useState(0);
  return (
    <>
      <p>
        {name}:{number}
      </p>
      <button onClick={() => setName("新计数器" + Date.now())}>新计数器</button>

      <button onClick={() => setNumber(number + 1)}> + </button>
    </>
  );
}
function render() {
  // 每次重新渲染的时候,都将 workInProgressHook 指向 firstWorkInProgressHook
  workInProgressHook = firstWorkInProgressHook;
  ReactDOM.render(<Counter />, document.getElementById("root"));
}
render();

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值