React@16.x(22)HOOK,useState 的原理

1,介绍

1,出现时间点:在 React@16.8.0 出现。

2,目的:为了增强函数组件的功能,用于替代类组件(类组件中不能使用 HOOK)。

3,原因:类组件中有一些比较麻烦的问题:this 指向、繁琐的生命周期等问题。

4,特点:本质上就是一个函数,该函数可以挂载(hook)一些功能。

最常用的2个HOOK:

  • useState,作为状态使用。
  • useEffect,作为生命周期使用。

2,useState

一个函数组件中可以有多个状态,这种做法非常有利于横向切分关注点。

2.1,使用

简单举例:

import React, { useState } from "react";

export default function App() {
    const [n, setN] = useState(0); //使用一个状态,该状态的默认值是0
    return (
        <div>
            <button
                onClick={() => {
                    setN(n - 1);
                }}
            >
                -
            </button>
            <span>{n}</span>
            <button
                onClick={() => {
                    setN(n + 1);
                }}
            >
                +
            </button>
        </div>
    );
}

2.2,原理

正常情况下,函数组件重新渲染(重新运行),函数体中的内容不会保留,并且会返回新的内容。那状态是如何保持的

在之前的渲染流程中提到:React 元素会创建React 节点,ReactDOM 会通过节点来进行渲染

这里做一些补充:

在创建节点的过程中,也会创建并维护一个状态数组,它附着在节点上

第N次调用 useState 时,会检查节点对应的状态数组是否存在下标N

  • 不存在(初次渲染),则使用默认值创建一个状态,并将该状态加入到下标N的位置。
  • 存在(再次渲染),忽略掉默认值,直接取对应下标的状态值。

另外,正因为 React节点是通过 React 元素创建的,所以React 元素之间相互独立导致每个状态数组 也是独立的,互不影响。

2.3,注意点

1,所有的 useState 最好写到函数起始位置,便于阅读。

至少要写到第一次使用该状态之前。

2,useState严禁出现在代码块中(判断,循环)。

3,useState 返回的函数(数组第2项),引用不变。

函数组件多次渲染时,该状态函数是同一个,为了节省内存。

4,使用状态函数修改状态时,若传递的状态值未做修改(使用Object.is() 比较),不会导致重新渲染。这是为了优化效率。

5,强制刷新。如果状态值是一个对象,则可通过传入一个空对象来实现强制渲染。(2个对象引用不同)

export default function App() {
    console.log("App Render");
    const [, forceUpdate] = useState({});
    return (
        <div>
            <button
                onClick={() => {
                    forceUpdate({});
                }}
            >
                强制刷新
            </button>
        </div>
    );
}

6,使用状态函数修改状态时,新传入的值会直接替换旧值,而不是合并。

// 使用解构,保留之前的状态
export default function App() {
    const [data, setData] = useState({ x: 1, y: 2 });
    return (
        <div>
            <span>{data.x}</span>
            <span>{data.y}</span>
            <button
                onClick={() => {
                    setData({
                        ...data,
                        x: data.x + 1,
                    });
                }}
            >
                x+1
            </button>
        </div>
    );
}

7,如果状态之间没有必然联系,应该分开处理,而不是合并为一个对象。

8,和类组件的状态相似,函数组件中改变状态也可能是异步的(比如DOM事件),多个状态的修改会合并,以提高效率。

所以,不能信任之前的状态。如果需要用到之前的状态,可以使用函数参数。

和类组件的 setState 一样,如果参数是函数的话,会将每个状态函数的函数参数放到一个队列中,按顺序执行。队列执行完毕后,再更新真正的 state,再执行 render(只执行了1次)。

举例:每次点击按钮,n+2,同时只打印一次 App render

import React, { useState } from "react";

export default function App() {
    console.log("App render");
    const [n, setN] = useState(0);
    return (
        <div>
            <span>{n}</span>
            <button
                onClick={() => {
                    // setN(n + 1)
                    // setN(n + 1) // 此时,n的值仍然是0

                    setN((prevN) => prevN + 1);
                    setN((prevN) => prevN + 1);
                }}
            >
                +
            </button>
        </div>
    );
}

以上。

相关推荐

  1. React@16.x22)HOOK,useState 原理

    2024-06-11 10:36:02       13 阅读
  2. React@16.x23)useEffect

    2024-06-11 10:36:02       12 阅读
  3. React@16.x26)useContext

    2024-06-11 10:36:02       9 阅读
  4. React@16.x27)useCallBack

    2024-06-11 10:36:02       9 阅读
  5. React@16.x28)useMemo

    2024-06-11 10:36:02       8 阅读
  6. React@16.x25)useReducer

    2024-06-11 10:36:02       12 阅读
  7. React@16.x19)事件处理

    2024-06-11 10:36:02       11 阅读
  8. React@16.x24)自定义HOOK

    2024-06-11 10:36:02       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-11 10:36:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-11 10:36:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-11 10:36:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-11 10:36:02       18 阅读

热门阅读

  1. 【Redis】Redis的数据淘汰策略有哪些

    2024-06-11 10:36:02       10 阅读
  2. SQL的执行顺序

    2024-06-11 10:36:02       7 阅读
  3. Web前端与PHP:深度解析与未来展望

    2024-06-11 10:36:02       10 阅读
  4. 特别名词Test Paper3

    2024-06-11 10:36:02       9 阅读
  5. 微信小程序真机调试连不上

    2024-06-11 10:36:02       7 阅读
  6. MATLAB 论文绘图规范标注

    2024-06-11 10:36:02       11 阅读
  7. 模块间通信

    2024-06-11 10:36:02       7 阅读