React-useState讲解
useState
让页面“动”起来
例如实现一个 click 计数功能,普通变量无法实现。即:修改普通变量无法触发组件的更新 rerender
通过 useState 即可实现。
state 是什么
State, A component’s memory —— 这个比喻非常好!
- props 父组件传递过来的信息
- state 组件自己内部的状态,不对外
每次 state 变化,都会触发组件更新,从新渲染页面。
代码演示,参考 react-ts-demo 中 pages/StateDemo1.tsx
import React, { FC, useState } from 'react'const Demo: FC = () => {// let count = 0 // 普通的 js 变量,无法触发组件的更新const [count, setCount] = useState(0) // useState 可以触发组件的更新,// const [name, setName] = useState('双越')function add() {// count++// setCount(count + 1)setCount(count => count + 1) // 使用函数,state 更新不会被合并setCount(count => count + 1)setCount(count => count + 1)setCount(count => count + 1)setCount(count => count + 1)// setCount(count => count + 1)console.log('cur count ', count) // 异步更新,无法直接拿到最新的 state 值}return (<div><button onClick={add}>add {count}</button></div>)
}export default Demo
state 的特点
异步更新
代码演示
PS:setState 传入函数,可同步更新
可能会被合并
代码演示
不可变数据
state 可以是任意 JS 类型,不仅仅是值类型。
不可直接修改 state ,而要 setState 新值。
代码演示
PS:函数组件,每个更新函数从新执行,state 被重置,而不是被修改。state 可以理解为 readOnly
immer
Immer 简化了不可变数据结构的处理。特别是对于 JS 语法没那么熟悉的人。
代码演示,参考 react-ts-demo 中 pages/ImmerDemo1.tsx
import React, { FC, useState } from 'react'
import produce from 'immer'const Demo: FC = () => {// const [userInfo, setUserInfo] = useState({ name: '柚子', age: 20 })// function changeAge() {// // // **不可变数据** - 不去修改 state 的值,而是要传入一个新的值 —— 重要!// // setUserInfo({// // ...userInfo,// // age: 21,// // })// setUserInfo(// produce(draft => {// draft.age = 21// })// )// }const [list, setList] = useState(['x', 'y'])function addItem() {// // **不可变数据** - 不去修改 state 的值,而是要传入一个新的值 —— 重要!// setList(list.concat('z'))// // setList([...list, 'z'])setList(produce(draft => {draft.push('z')}))}return (<div><h2>state 不可变数据</h2>{/* <div>{JSON.stringify(userInfo)}</div><button onClick={changeAge}>change age</button> */}<div>{JSON.stringify(list)}</div><button onClick={addItem}>add item</button></div>)
}export default Demo
实战:List 页面使用 state
- 使用 state
- 使用 immer
- push
- 修改 isPublish
代码参考 pages/List2.tsx
import React, { FC, useState, useEffect } from 'react'
import produce from 'immer'
import QuestionCard from './components/QuestionCard'// 组件是一个函数(执行返回 JSX 片段),组件初次渲染执行这个函数
// 任何 state 更新,都会触发组件的更新(重新执行函数)
const List2: FC = () => {useEffect(() => {console.log('加载 ajax 网络请求')return () => {console.log('销毁')}}, []) // 无依赖,组件初次渲染时执行// const [count, setCount] = useState(0)const [questionList, setQuestionList] = useState([{ id: 'q1', title: '问卷1', isPublished: false },{ id: 'q2', title: '问卷2', isPublished: true },{ id: 'q3', title: '问卷3', isPublished: false },{ id: 'q4', title: '问卷4', isPublished: true },])// useEffect(() => {// console.log('question list changed')// }, [questionList])// useEffect(() => {// console.log('count changed')// }, [count, questionList])function add() {// setCount(count + 1)const r = Math.random().toString().slice(-3)// setQuestionList(// // 新增 concat// questionList.concat({// id: 'q' + r,// title: '问卷' + r,// isPublished: false,// })// )// immer 的方式setQuestionList(produce(draft => {draft.push({id: 'q' + r,title: '问卷' + r,isPublished: false,})}))}function deleteQuestion(id: string) {// // 不可变数据// setQuestionList(// // 删除 filter// questionList.filter(q => {// if (q.id === id) return false// else return true// })// )// immer 的方式setQuestionList(produce(draft => {const index = draft.findIndex(q => q.id === id)draft.splice(index, 1)}))}function publishQuestion(id: string) {// setQuestionList(// // 修改 map// questionList.map(q => {// if (q.id !== id) return q// return {// ...q,// isPublished: true,// }// })// )// immer 的方式setQuestionList(produce(draft => {const q = draft.find(item => item.id === id)if (q) q.isPublished = true}))}return (<div><h1>问卷列表页2</h1><div>{questionList.map(question => {const { id, title, isPublished } = questionreturn (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}deleteQuestion={deleteQuestion}publishQuestion={publishQuestion}/>)})}</div><div><button onClick={add}>新增问卷</button></div></div>)
}export default List2
代码参考 /components/QuestionCard
import React, { FC, useEffect } from 'react'
import classnames from 'classnames'
// import './QuestionCard.css'
import styles from './QuestionCard.module.scss'// ts 自定义类型
type PropsType = {id: stringtitle: stringisPublished: booleandeleteQuestion?: (id: string) => voidpublishQuestion?: (id: string) => void
}// FC - functional component
const QuestionCard: FC<PropsType> = props => {const { id, title, isPublished, deleteQuestion, publishQuestion } = propsfunction publish(id: string) {publishQuestion && publishQuestion(id)}function del(id: string) {deleteQuestion && deleteQuestion(id)}// useEffect(() => {// console.log('question card mounted')// return () => {// console.log('question card unmounted', id) // 销毁// }// // 生命周期:创建,更新(state 变化),销毁// }, [])// let itemClassName = 'list-item'// if (isPublished) itemClassName += ' published'// // 逻辑稍微复杂// const itemClassName = classnames('list-item', { published: isPublished })// const itemClassName = classnames({// 'list-item': true,// published: isPublished,// })const listItemClass = styles['list-item']const publishedClass = styles.publishedconst itemClassName = classnames({[listItemClass]: true,[publishedClass]: isPublished,})return (<div key={id} className={itemClassName}><strong>{title}</strong> {/* 条件判断 */}{isPublished ? <span className={styles['published-span']}>已发布</span> : <span>未发布</span>} <buttononClick={() => {publish(id)}}>发布问卷</button> <buttononClick={() => {del(id)}}>删除问卷</button></div>)
}export default QuestionCard
最重要的就是:不可变数据 —— 这是 React state 的核心
相关文章:
React-useState讲解
useState 让页面“动”起来 例如实现一个 click 计数功能,普通变量无法实现。即:修改普通变量无法触发组件的更新 rerender 通过 useState 即可实现。 state 是什么 State, A component’s memory —— 这个比喻非常好! props 父组件传…...
混币器是什么,波卡跨链交易平台
混币器是什么 混币器是一种加密货币工具,主要功能是将用户的加密货币与其他众多用户的加密货币混合在一起,打乱资金的流向和交易痕迹,使得加密货币的来源和去向难以追踪,从而增加交易的匿名性和隐私性。以下是对其工作流程和相关举例的介绍: 工作流程 用户首先将自己的加…...
【PHP】双方接口通信校验服务
请求方 使用 ApiAuthService::buildUrl($domain, [terminal > 1, ts > time()]); //http://域名/adminapi/login/platformLogin?signF7FE8A150DEC18BE8A71C5059742C81A&terminal1&ts1736904841接收方 $getParams $this->request->get();$validate ApiA…...
Web第一次作业
目录 题目 html代码 index login register css代码 base index login register 效果展示 index login register 题目 实现一个登录页面、实现一个注册页面;实现一个主页 - 登录页面:login.html - 注册页面:register.html - 主页…...
CentOS 6.8 安装 Nginx
个人博客地址:CentOS 6.8 安装 Nginx | 一张假钞的真实世界 提前安装: # sudo yum install yum-utils 一般情况下这个工具系统已经安装。 创建文件/etc/yum.repos.d/nginx.repo,输入内容如下: [nginx-stable] namenginx stab…...
网络网络层ICMP协议
网络网络层ICMP协议 1. ICMP 协议介绍 ICMP(Internet Control Message Protocol)是 TCP/IP 协议簇中的网络层控制报文协议。用于在 IP 主机、路由器之间传递控制消息,提供可能有关通信问题的反馈信息。 以及用于网络诊断或调试(…...
当父级元素设置了flex 布局 ,两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 (css 样式问题)
一、问题 遇到个样式问题,当父级元素设置了flex 布局 ,两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 (拖拽浏览器 使页面变小) 二、解决方法 .father{min-height: 600px;width: 100%;display: flex…...
Vue.js组件开发-如何实现路由懒加载
在Vue.js应用中,路由懒加载是一种优化性能的技术,它允许在需要时才加载特定的路由组件,而不是在应用启动时加载所有组件。这样可以显著减少初始加载时间,提高用户体验。在Vue Router中,实现路由懒加载非常简单…...
灵活妙想学数学
灵活妙想学数学 题1:海星有几只? 一共有12只海洋生物,分别是5只脚的海星,8只脚的章鱼和10只脚的鱿鱼,这些海洋动物的脚一共有87只,每种生物至少有1只,问海星有几只? 解:…...
使用 Multer 上传图片到阿里云 OSS的两种方式
文件上传到哪里更好? 上传到服务器本地 上传到服务器本地,这种方法在现今商业项目中,几乎已经见不到了。因为服务器带宽,磁盘 IO 都是非常有限的。将文件上传和读取放在自己服务器上,并不是明智的选择。 上传到云储存…...
破解合同管理之痛,开启智能化管理新模式
合同管理是采购管理中的一项重要环节,涉及合同洽谈、草拟、签订、生效、履行、失效全过程。随着企业业务规模的发展壮大,企业与各类供应商之间的合作往来更加频繁,需要签署和管理的合同文件也不断增多,如何提升合同管理效率成为企…...
Linux-day06
第14章 进程管理(重点) 进程基本介绍 程序运行起来就是一个进程 1.程序和进程的关系 2.在Linux中有两种方式执行,一种叫前台,一种后台 ps指令详解 显示系统执行的进程 USER:进程执行用户 PID:进程号 …...
源码编译安装httpd 2.4,提供系统服务管理脚本并测试
总结需要安装的包 sudo yum groupinstall "Development Tools" -y #httpd的依赖包yum install tar -y #tar压缩包sudo yum install apr-devel apr-util-devel #APR库 提供跨平台接口的库sudo yum install pcre pcre-devel # PCRE库和 pcre-config工具--提供PCRE库…...
Linux固定ip
进入etc/sysconfig/network-scripts目录 cd /etc/sysconfig/network-scripts 编辑ifcfg-ens33文件 vi ifcfg-ens33 将BOOTPROTO的值改为“static”,在文档最后添加需要的固定IP BOOTPROTO"static" IPADDR192.168.132.136点击按键“esc”,…...
Java 输入输出流(上)
目录 1.Java 输入输出流 2.Java File类 3.Java File类目录 1.创建目录 2.列出目录中的文件 4.Java File类文件 1.文件的创建与删除 2.运行可执行文件 5.Java 文件字节输入流(1) 6.Java 文件字节输入流(2) 1.使用输入流读取字节 2.关闭流 7.Java 文件字节输出流(1…...
mysql、oracle、sqlserver的区别
一、保存数据的持久性: MySQL:是在数据库更新或者重启,则会丢失数据。 Oracle:把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,可以随时恢复。 SqlServer:2…...
Java+Maven+GDAL
下载已经编译好的压缩包,下载地址 解压 jar 包 release-1930-x64-dev.zip\release-1930-x64\bin\gdal\java 目录下 打成Maven依赖 mvn install:install-file -Dfilegdal-3.10.1.jar -DgroupIdorg.gdal -DartifactIdgdal -Dversion3.10.1 -Dpackagingjar -Dgener…...
初识算法和数据结构P1:保姆级图文详解
文章目录 前言1、算法例子1.1、查字典(二分查找算法)1.2、整理扑克(插入排序算法)1.3、货币找零(贪心算法) 2、算法与数据结构2.1、算法定义2.2、数据结构定义2.3、数据结构与算法的关系2.4、独立于编程语言…...
【Go】Go Gorm 详解
1. 概念 Gorm 官网:https://gorm.io/zh_CN/docs/ Gorm:The fantastic ORM library for Golang aims to be developer friendly,这是官网的介绍,简单来说 Gorm 就是一款高性能的 Golang ORM 库,便于开发人员提高效率 那…...
【IDEA版本升级JDK21报错方法引用无效 找不到符号】
java: 方法引用无效 找不到符号 符号: 方法 getFirst() 位置: 接口 java.util.List 升级JDK21版本遇到问题,报错找不到符号 但是点进去又能发现这个函数,证明能够找到这个方法,但是就是报错 java: 方法引用无效 找不到符号 符号: …...
从测速到配置:一套完整的cFosSpeed网络加速保姆级教程(适用于小白)
从零开始掌握cFosSpeed:网络加速全流程实战指南对于经常进行在线游戏、视频会议或大文件传输的用户来说,网络延迟和带宽利用率低下往往是影响体验的关键痛点。cFosSpeed作为一款专业的网络流量优化工具,能够显著改善这些问题,但许…...
从分立逻辑到单片机:基于ATmega8的MIDI通道分析仪设计与实现
1. 项目概述:从分立逻辑到单片机的MIDI通道分析仪进化史二十年前,当我在《Elektor》杂志上发表第一版MIDI通道分析仪时,整个数字音乐世界还处于一个相当“硬核”的阶段。那个版本的设计,用今天的话来说,简直就是一场“…...
ncmdumpGUI终极指南:3分钟搞定网易云音乐NCM文件转换
ncmdumpGUI终极指南:3分钟搞定网易云音乐NCM文件转换 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 还在为网易云音乐的NCM加密格式而烦恼吗&…...
监控摄像头小众场景爆发,融合类产品成新蓝海
随着户外运动热潮的持续和物联网技术的全面落地,打猎相机市场在2025年迎来了真正的爆发期,并在2026年继续向智能化、网联化深度演进。根据最新的行业监测数据,2025年全球消费类IPC(网络摄像机)出货量突破1.92亿台&…...
WSABuilds安装挑战:从“包注册失败“到“架构不匹配“的完整解决指南
WSABuilds安装挑战:从"包注册失败"到"架构不匹配"的完整解决指南 【免费下载链接】WSABuilds Run Windows Subsystem For Android on your Windows 10 and Windows 11 PC using prebuilt binaries with Google Play Store (MindTheGapps) and/o…...
终极指南:如何在macOS上使用eqMac专业音频均衡器提升音质体验
终极指南:如何在macOS上使用eqMac专业音频均衡器提升音质体验 【免费下载链接】eqMac macOS System-wide Audio Equalizer & Volume Mixer 🎧 项目地址: https://gitcode.com/gh_mirrors/eq/eqMac 你是否厌倦了macOS系统单调的音频效果&#…...
三招识别“纪律高危”学生?K-Means聚类助你构建精准考勤画像
助睿实验3 - 学生用户画像 - 考勤主题扩展标签构建第一部分:实验背景1.1实验目的本实验旨在基于已完成的学生考勤主题标签表,掌握使用K-Means聚类算法对学生考勤行为进行自动分群的核心技能。具体任务包括:通过迟到、早退、请假、校服违规次数…...
基于堆叠集成学习的脑膜炎早期预警模型:从EHR数据挖掘到临床决策支持
1. 项目概述与核心价值在急诊室(ER)和重症监护室(ICU)里,时间就是生命,而脑膜炎的诊断恰恰是和时间赛跑。这种包裹着大脑和脊髓的脑膜炎症,起病急、进展快,一旦延误,神经…...
微波流式细胞术与机器学习融合:实现非球形微塑料全电子化形态检测
1. 项目概述与核心挑战微塑料污染已成为全球性的环境与健康威胁,其检测与表征是环境科学领域的一项关键技术挑战。传统的主流检测方法,如傅里叶变换红外光谱(FTIR)和拉曼光谱,虽然能够提供高精度的化学成分鉴定&#x…...
从PointNet到Transformer:聊聊‘参数共享’这个省内存又提性能的炼丹技巧
从PointNet到Transformer:参数共享如何重塑深度学习效率 在深度学习模型日益复杂的今天,算法工程师们不断面临一个核心矛盾:如何在保持模型性能的同时,有效控制参数规模?当我们处理点云、序列或图结构这类不规则数据时…...
