React: Day_1

React - 机制

Chapter 1


  • 渲染与变量

    • React的函数式组件会在每次状态发生变化时,重新执行。如果在hook中声明了普通的变量,那么会在每次状态发生变化重新渲染时,重新进行初始化。

    • export default function() {
          let x = 2;
          // 点击后x虽然加1了,但是由于没有被React监听,所以页面并不会重新渲染
          return <div onClick={() => x += 1}>{x}</div>
      }
      
    • React渲染条件是状态发生变化时,才会重新渲染。所以需要引用useState来获取一个可以创建变量被React监听的函数。(普通变量即使更新,React也不会触发渲染)

    • import { useState } from 'react';
      export default function() {
          const [ count, setCount ] = useState(0);
          let x = 1;
          // 点击后 x 虽然会加2,并且有被React监听的 count 变量。count + 1发生重新渲染,但是重新渲染导致 x 又被初始化为 1
          return (
          	<div onClick={() => {
              	x += 2;
                  setCount(count + 1);
              }}></div>
          )
      }
      
  • React的渲染阶段

    • 分为三个阶段:触发、渲染、提交
    • 触发只有两种:初次渲染、状态更新
    • 渲染:初次渲染会调用React的根组件createRoot来创建组件,后续只有更新状态才会触发React的重新渲染。
    • 提交:React会使用DOM Diff算法来减少重复渲染,只更新状态有变化的组件的DOM
  • State

    • 由React提供的hook,声明的state只会在初次渲染的时候进行初始化,之后都会保持上次的结果值。因为它是被挂载在函数外类似于架子上,以确保每次渲染后也能拿到上次的值。

    • 触发setState后,React会先挂载起来。然后会返回一个快照,就是state改变前的值。在该作用域下使用的state值都会是这个快照值,即使使用的时候state已经更新!

    • export default function() {
          const [count, setCount] = useState(0);
          
          return (
          	<div onClick={async () => {
                  setCount(count + 1);
                  // 即使这个接口在state更新后才调用,也会使用state的快照,也就是0
                  await new Promise(
                      (resolve) => setTimeout(
                          () => resolve(count)
                      , 999999));
              }}></div>
          )
      }
      
    • 如果在同一个作用域下同时调用相同的多个setState,React会进行批处理,值执行最后一个setState

    • export default function() {
          const [count, setCount] = useState(0);
          
          return (
          	<div onClick={() => {
                  setCount(count + 1);
                  setCount(count + 2);
                  // 只会执行最后一次的 setCount 也就是 3
                  setCount(count + 3);
              }}></div>
          )
      }
      
    • 执行async函数,即使在state发生改变了,接口还没await完成也不影响该函数的继续完成

    • export default function() {
          const [count, setCount] = useState(0);
          
          return (
          	<div onClick={async () => {
              	setCount(1);
                  console.log('enter');
                  // 假设该接口会在count状态更新后,才执行完成
                  await getApi();
                  console.log('out');
                  // 结果是: enter、 count值改变、 getApi执行完成、 out
              }}></div>
          )
      }
      
  • refstate的区别

    • 相同点:都会挂载在函数外的架子上,确保每次渲染后,值不会被初始化。

    • 不同点:ref其实就是一个包裹的普通对象{ current: value },并且在更改ref值后并不会触发React的重新渲染。ref可以在任何阶段改变值,并且确保他能被实时更新。而state是异步更新。

    • export default function() {
          const [count, setCount] = useState(0);
          const num = useRef(null);
          
          return (
          	<div
              	onClick={() => {
                      num.current = 2;
                      // 结果会是 0 + 2 = 2
                      setCount(count + num.current);
                  }}
              ></div>
          )
      }
      
  • ref像自定义组件传递ref

    • 直接传递会无效,需要通过React的forwardRef来包裹该函数组件,然后该函数组件的参数将会添加ref,React.forwardRef((props, ref) => <div ref={ref}></div>)
  • state同步更新

    • 如果需要state进行同步更新,可以调用react-dom中的flushSync,通过flushSync(callback)该回调函数中的state更新都将同步
posted @   这样那样如此如此  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示