#添加交互

#步骤

  • 响应事件
  • state:组件的记忆
  • 渲染和提交*
  • state:快照(闭包)
  • 把一系列 state 更新加入队列*
  • 更新 state 中的对象:不是更改而是拷贝(推荐库 use-immer)
  • 更新 state 中的数组

#渲染和提交

#三个步骤

  • 触发渲染 (初始化或者改变状态)
  • 渲染组件 (reconciler)
  • 绘制 DOM (renderer)

#触发渲染

  • 组件初次渲染
  • 组件(或者其祖先之一)的状态发生了改变

注意!props 改变并不是渲染原因,不要被 memo 函数误导

#渲染组件

  • 初次渲染, React 会调用根组件
  • 后续渲染, React 会调用内部状态更新触发了渲染的函数组件,并计算尽量少的更新 DOM 操作(diff,尽量复用)

这个过程是递归的,如果更新后的组件会返回某个另外的组件,那么 React 接下来就会渲染那个组件,直到没有更多的嵌套组件

#绘制 DOM

  • 初次渲染, React 会使用 appendChild() DOM API 将其创建的所有 DOM 节点放在屏幕上
  • 重渲染, React 将应用最少的必要操作(在渲染组件时计算!),以使得 DOM 与最新的渲染输出相互匹配

#把一系列 state 更新加入队列

#批处理

事件处理函数及其中任何代码执行完成 之后,UI 才会更新。这种特性也就是批处理

#在下次渲染前多次更新同一个 state

import { useState } from 'react'

export default function Counter() {
  const [number, setNumber] = useState(0)

  return (
    <>
      <h1>{number}</h1>
      <button
        onClick={() => {
          setNumber((n) => n + 1)
          setNumber((n) => n + 1)
          setNumber((n) => n + 1)
        }}
      >
        +3
      </button>
    </>
  )
}