当前位置: 首页 > news >正文

React第十章(useState)

useState

useState 是一个 React Hook,允许函数组件在内部管理状态。

组件通常需要根据交互更改屏幕上显示的内容,例如点击某个按钮更改值,或者输入文本框中的内容,这些值被称为状态值也就是(state)。

使用方法

useState 接收一个参数,即状态的初始值,然后返回一个数组,其中包含两个元素:当前的状态值和一个更新该状态的函数

const [state, setState] = useState(initialState)

注意事项

useState 是一个 Hook,因此你只能在 组件的顶层 或自己的 Hook 中调用它。你不能在循环或条件语句中调用它。

在严格模式中,React 将 两次调用初始化函数,以 帮你找到意外的不纯性。这只是开发时的行为,不影响生产

用法

添加一个状态

const Card = () => {let [index, setIndex] = useState(0)let [name, setName] = useState('小满')let [arr, setArr] = useState([1, 2, 3])
}

按照惯例使用 数组解构 来命名状态变量,例如 [index, setIndex]。

useState 返回一个只包含两个项的数组:

  1. 该状态变量 当前的 state,最初设置为你提供的 初始化 state
  2. set 函数,它允许你在响应交互时将 state 更改为任何其他值。

要更新屏幕上的内容,请使用新状态调用 set 函数:

调用 set 函数更新 state 将会重新渲染组件

function changeName () {setName('大满')
}

React 会存储新状态,使用新值重新渲染组件,并更新 UI。

完整版案例(基本数据类型)

import { useState } from "react"
function App() {let [name, setName] = useState('小满') //数字 布尔值 null undefined 都可以直接赋值 一样的const heandleClick = () => {setName('大满')}return (<><button onClick={heandleClick}>更改名称</button><div>{name}</div></>)
}
export default App

完整版案例(复杂数据类型)

数组

在React中你需要将数组视为只读的,不可以直接修改原数组,例如:不可以调用 arr.push() arr.pop() 等方法。

下面是常见数组操作的参考表。当你操作 React state 中的数组时,你需要避免使用左列的方法,而首选右列的方法:

避免使用 (会改变原始数组)推荐使用 (会返回一个新数组)
添加元素 push,unshiftconcat,[…arr] 展开语法(例子)
删除元素 pop,shift,splicefilter,slice(例子)
替换元素 splice,arr[i] = … 赋值map(例子)
排序 reverse,sort先将数组复制一份(例子)
数组新增数据

创建一个新数组,包含了原始数组的所有元素,然后在末尾添加新元素,如果想在头部添加新元素,返过来即可。

import { useState } from "react"
function App() {let [arr, setArr] = useState([1, 2, 3])const heandleClick = () => {setArr([...arr,4]) //末尾新增 扩展运算符//setArr([0,...arr]) 头部新增 扩展运算符}return (<><button onClick={heandleClick}>更改值</button><div id="aaa">{arr}</div></>)
}
export default App
数组删除数据

使用filter过滤掉不需要的元素即可。

import { useState } from "react"
function App() {let [arr, setArr] = useState([1, 2, 3])const heandleClick = () => {setArr(arr.filter((item) => item !== 1)) //删除指定元素}return (<><button onClick={heandleClick}>更改值</button><div id="aaa">{arr}</div></>)
}
export default App
数组替换数据

使用map筛选出需要替换的元素,然后替换为新的元素,其他元素保持不变。

import { useState } from "react"
function App() {let [arr, setArr] = useState([1, 2, 3])const heandleClick = () => {setArr(arr.map(item => {return item == 2 ? 666 : item}))}return (<><button onClick={heandleClick}>更改值</button><div id="aaa">{arr}</div></>)
}
export default App
指定位置插入元素

案例在2后面插入2.5,通过slice,截取前面的元素,因为slice返回一个新的数组,然后在中间插入我们需要插入的元素,然后把末尾的元素也通过slice截取出来,拼接到后面。

slice文档 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

import { useState } from "react"
function App() {let [arr, setArr] = useState([1, 2, 3])const heandleClick = () => {let startIndex = 0let endIndex = 2;setArr([...arr.slice(startIndex, endIndex),2.5,...arr.slice(endIndex)])}return (<><button onClick={heandleClick}>更改值</button><div id="aaa">{arr}</div></>)
}
export default App
排序旋转等

案例,创建一个新数组,然后通过sort排序。

import { useState } from "react"
function App() {let [arr, setArr] = useState([1, 2, 3])const heandleClick = () => {let newList = [...arr].map(v => v + 1) //拷贝到新数组newList.sort((a, b) => b - a)//newList.reverse()旋转setArr(newList)}return (<><button onClick={heandleClick}>更改值</button><div id="aaa">{arr}</div></>)
}
export default App
对象

useState可以接受一个函数,可以在函数里面编写逻辑,初始化值,注意这个只会执行一次,更新的时候就不会执行了。

在使用setObject的时候,可以使用Object.assign合并对象 或者 … 合并对象,不能单独赋值,不然会覆盖原始对象。

import { useState } from "react"
function App() {let [obj, setObject] = useState(() => {const date = new Date().getFullYear() + '-' + (new Date().getMonth() + 1) + '-' + new Date().getDate()return {date,name: '小满',age: 25}})const heandleClick = () => {setObject({...obj,name: '大满'})//setObject(Object.assign({}, obj, { age: 26 })) 第二种写法}return (<><button onClick={heandleClick}>更改值</button><div>日期:{obj.date}</div><div>姓名:{obj.name}</div><div>年龄:{obj.age}</div></>)
}
export default App

useState更新机制

异步机制

useState set函数是异步更新的来看下面的案例:

import { useState } from "react"
function App() {let [index, setIndex] = useState(0)const heandleClick = () => {setIndex(index + 1)console.log(index,'index') //0}return (<><h1>Index:{index}</h1><button onClick={heandleClick}>更改值</button></>)
}
export default App

此时index应该打印1,但是还是0,因为我们正常编写的代码是同步的,所以会先执行,而set函数是异步的所以后执行,这么做是为了性能优化,因为我们要的是结果而不是过程。

内部机制

当我们多次以相同的操作更新状态时,React 会进行比较,如果值相同,则会屏蔽后续的更新行为。自带防抖的功能,防止频繁的更新。

案例:

import { useState } from "react"
function App() {let [index, setIndex] = useState(0)const heandleClick = () => {setIndex(index + 1) //1setIndex(index + 1) //1setIndex(index + 1) //1console.log(index,'index')}return (<><h1>Index:{index}</h1><button onClick={heandleClick}>更改值</button></>)
}
export default App

结果是1并不是3,因为setIndex(index + 1)的值是一样的,后续操作被屏蔽掉了,阻止了更新。

为了解决这个问题,你可以向setIndex 传递一个更新函数,而不是一个状态。

import { useState } from "react"
function App() {let [index, setIndex] = useState(0)const heandleClick = () => {setIndex(index => index + 1) //1setIndex(index => index + 1) //2setIndex(index => index + 1) //3}return (<><h1>Index:{index}</h1><button onClick={heandleClick}>更改值</button></>)
}
export default App
  1. index => index + 1 将接收 0 作为待定状态,并返回 1 作为下一个状态。
  2. index => index + 1 将接收 1 作为待定状态,并返回 2 作为下一个状态。
  3. index => index + 1 将接收 2 作为待定状态,并返回 3 作为下一个状态。

现在没有其他排队的更新,因此 React 最终将存储 3 作为当前状态。

按照惯例,通常将待定状态参数命名为状态变量名称的第一个字母,例如 prevIndex 或者其他你觉得更清楚的名称。

相关文章:

  • windows上安装mingw教程及mingw64国内下载地址汇总
  • 【JavaEE】http/https 超级详解
  • 六,MyBatis-Plus 扩展功能(逻辑删除,通用枚举,字段类型处理,自动填充功能,防全表更新与删除插件,MybatisX快速开发插件)
  • css的盒模型
  • 数据集-目标检测系列-豹子 猎豹 检测数据集 leopard>> DataBall
  • Spring Boot框架下的足球青训俱乐部后台开发
  • 数据分析-28-交互式数据分析EDA工具和低代码数据科学工具
  • C++ STL(1)迭代器
  • 速刷DuckDB官网24小时-掌握核心功法
  • 基于Hive和Hadoop的电商消费分析系统
  • 新农人的求索:既要种菜,也要种钱
  • web开发(1)-基础
  • 2024年7月大众点评乌鲁木齐美食店铺基础信息
  • FFmpeg源码:avio_skip函数分析
  • windows10使用bat脚本安装前后端环境之msyql5.7安装配置并重置用户密码
  • ----------
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • Android单元测试 - 几个重要问题
  • Brief introduction of how to 'Call, Apply and Bind'
  • Java-详解HashMap
  • js对象的深浅拷贝
  • Octave 入门
  • opencv python Meanshift 和 Camshift
  • 从零开始学习部署
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 深度学习中的信息论知识详解
  • 鱼骨图 - 如何绘制?
  • raise 与 raise ... from 的区别
  • 从如何停掉 Promise 链说起
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ​Spring Boot 分片上传文件
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • #微信小程序:微信小程序常见的配置传旨
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • #知识分享#笔记#学习方法
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (2)MFC+openGL单文档框架glFrame
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (C语言)逆序输出字符串
  • (c语言+数据结构链表)项目:贪吃蛇
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (Java入门)抽象类,接口,内部类
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (顺序)容器的好伴侣 --- 容器适配器
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET CLR基本术语
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 服务 ServiceController
  • .Net 垃圾回收机制原理(二)
  • .NET/C# 使窗口永不获得焦点
  • .net6Api后台+uniapp导出Excel
  • .NetCore实践篇:分布式监控Zipkin持久化之殇