总结:React 中的 state 状态

发布于:2024-03-11 ⋅ 阅读:(43) ⋅ 点赞:(0)

☝️上文提及:可以通过组件中的重要信息是否由组件自身 state 还是外部 prop 驱动来区分「受控组件」&「非受控组件」。

换言之,props 是对外的,state 是对内的

  • props:只读,父组件通过 props 传递给子组件其所需要的状态;子组件内部不能直接修改props,只能在父组件中修改。
  • state:可变,是组件内部维护的一组用于反映组件UI变化的状态集合。

本篇会 ✓ 🇨🇳 总结 React 中的 state 状态

回顾一下1

① react 有两种原因会导致组件的渲染,其中 State setter 函数 更新变量会触发 React 渲染组件;
State 变量 用于保存渲染间的数据。

👀 State = 存放数据 + 触发重新渲染

存储数据

const [index, setIndex] = useState(0);

function handleClick() {
  setIndex(i => i + 1);
}
  1. index 的初始值被 useState(0) 设置为 0
  2. state 变量 (index) 会保存上次渲染的值;
  3. state setter 函数 (setIndex) 可以更新 state 变量并触发 React 重新渲染组件。
触发状态变更
触发渲染
第一次渲染\nindex = 0
setIndex(i => i + 1)
第二次渲染\n index = 1
以此类推

更新数据

更新对象

核心:把当前的数据复制到新对象中

const [person, setPerson] = useState({name: '', age: 0})

setPerson({
  ...person,
  age: e.target.value	// 只覆盖 age 字段
})

setPerson({
  ...person,
  [e.target.name]: e.target.value // 动态命名
})

‼️注意:... 展开语法本质是是“浅拷贝”——它只会复制一层。这使得它的执行速度很快,但是也意味着当你想要更新一个嵌套属性时,你必须得多次使用展开语法2

setPerson({
  ...person, // 复制其它字段的数据 
  artwork: { // 替换 artwork 字段 
    ...person.artwork, // 复制之前 person.artwork 中的数据
    city: 'New Delhi' // 但是将 city 的值替换为 New Delhi!
  }
});
更新数组

核心:将 React state 中的数组视为只读的

每次要更新一个数组时,需要把一个的数组传入 state 的 setting 方法中。

避免使用 (会改变原始数组) 推荐使用 (会返回一个新数组)
添加元素 pushunshift concat[...arr] 展开语法(例子
删除元素 popshiftsplice filterslice例子
替换元素 splicearr[i] = ... 赋值 map例子
排序 reversesort 先将数组复制一份(例子
批量更新

开篇:通过 state 阐述 React 渲染 setInterval 示例中曾提及:一个 state 变量的值永远不会在一次渲染的内部发生变化。

React 会等到事件处理函数中的 所有 代码都运行完毕再处理你的 state 更新。

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>
    </>
  )
}
  1. React 会将更新函数依次加入队列,以便在事件处理函数中的所有其他代码运行后进行处理。
  2. 在下一次渲染期间,React 会遍历队列并给你更新之后的最终 state。
批量处理
加入队列
更新队列
返回最终结果
触发渲染
2 + 1 = 3
1 + 1 = 2
0 + 1 = 1
将 n => n + 1 加入队列
将 n => n + 1 加入队列
将 n => n + 1 加入队列
修改DOM
最少原则
浏览器绘制

触发重新渲染

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

React 仅在渲染之间存在差异时才会更改 DOM 节点。

示例3:有一个组件,它每秒使用从父组件传递下来的不同属性重新渲染一次。
‼️注意,文本不会在组件重渲染时消失。

export default function Clock({ time }) {
  return (
    <>
      <h1>{time}</h1>
      <input />
    </>
  );
}

在这里插入图片描述

状态与渲染树中的位置相关: 相同位置的相同组件会使得 state 被保留下来,否则会重置。关于此部分的详实,在下一篇专题讲述!


  1. https://blog.csdn.net/ligang2585116/article/details/136219429 通过 state 阐述 React 渲染 ↩︎

  2. https://react.docschina.org/learn/updating-objects-in-state#updating-a-nested-object 更新一个嵌套对象 ↩︎

  3. https://react.docschina.org/learn/render-and-commit#step-3-react-commits-changes-to-the-dom React 把更改提交到 DOM 上 ↩︎


网站公告

今日签到

点亮在社区的每一天
去签到