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

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>&nbsp;{/* 条件判断 */}{isPublished ? <span className={styles['published-span']}>已发布</span> : <span>未发布</span>}&nbsp;<buttononClick={() => {publish(id)}}>发布问卷</button>&nbsp;<buttononClick={() => {del(id)}}>删除问卷</button></div>)
}export default QuestionCard

最重要的就是:不可变数据 —— 这是 React state 的核心

相关文章:

React-useState讲解

useState 让页面“动”起来 例如实现一个 click 计数功能&#xff0c;普通变量无法实现。即&#xff1a;修改普通变量无法触发组件的更新 rerender 通过 useState 即可实现。 state 是什么 State, A component’s memory —— 这个比喻非常好&#xff01; 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 题目 实现一个登录页面、实现一个注册页面&#xff1b;实现一个主页 - 登录页面&#xff1a;login.html - 注册页面&#xff1a;register.html - 主页…...

CentOS 6.8 安装 Nginx

个人博客地址&#xff1a;CentOS 6.8 安装 Nginx | 一张假钞的真实世界 提前安装&#xff1a; # sudo yum install yum-utils 一般情况下这个工具系统已经安装。 创建文件/etc/yum.repos.d/nginx.repo&#xff0c;输入内容如下&#xff1a; [nginx-stable] namenginx stab…...

网络网络层ICMP协议

网络网络层ICMP协议 1. ICMP 协议介绍 ICMP&#xff08;Internet Control Message Protocol&#xff09;是 TCP/IP 协议簇中的网络层控制报文协议。用于在 IP 主机、路由器之间传递控制消息&#xff0c;提供可能有关通信问题的反馈信息。 以及用于网络诊断或调试&#xff08;…...

当父级元素设置了flex 布局 ,两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 (css 样式问题)

一、问题 遇到个样式问题&#xff0c;当父级元素设置了flex 布局 &#xff0c;两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 &#xff08;拖拽浏览器 使页面变小&#xff09; 二、解决方法 .father{min-height: 600px;width: 100%;display: flex…...

Vue.js组件开发-如何实现路由懒加载

在Vue.js应用中&#xff0c;路由懒加载是一种优化性能的技术&#xff0c;它允许在需要时才加载特定的路由组件&#xff0c;而不是在应用启动时加载所有组件。这样可以显著减少初始加载时间&#xff0c;提高用户体验。在Vue Router中&#xff0c;实现路由懒加载非常简单&#xf…...

灵活妙想学数学

灵活妙想学数学 题1&#xff1a;海星有几只&#xff1f; 一共有12只海洋生物&#xff0c;分别是5只脚的海星&#xff0c;8只脚的章鱼和10只脚的鱿鱼&#xff0c;这些海洋动物的脚一共有87只&#xff0c;每种生物至少有1只&#xff0c;问海星有几只&#xff1f; 解&#xff1a…...

使用 Multer 上传图片到阿里云 OSS的两种方式

文件上传到哪里更好&#xff1f; 上传到服务器本地 上传到服务器本地&#xff0c;这种方法在现今商业项目中&#xff0c;几乎已经见不到了。因为服务器带宽&#xff0c;磁盘 IO 都是非常有限的。将文件上传和读取放在自己服务器上&#xff0c;并不是明智的选择。 上传到云储存…...

破解合同管理之痛,开启智能化管理新模式

合同管理是采购管理中的一项重要环节&#xff0c;涉及合同洽谈、草拟、签订、生效、履行、失效全过程。随着企业业务规模的发展壮大&#xff0c;企业与各类供应商之间的合作往来更加频繁&#xff0c;需要签署和管理的合同文件也不断增多&#xff0c;如何提升合同管理效率成为企…...

Linux-day06

第14章 进程管理&#xff08;重点&#xff09; 进程基本介绍 程序运行起来就是一个进程 1.程序和进程的关系 2.在Linux中有两种方式执行&#xff0c;一种叫前台&#xff0c;一种后台 ps指令详解 显示系统执行的进程 USER&#xff1a;进程执行用户 PID&#xff1a;进程号 …...

源码编译安装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”&#xff0c;在文档最后添加需要的固定IP BOOTPROTO"static" IPADDR192.168.132.136点击按键“esc”&#xff0c;…...

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的区别

一、保存数据的持久性&#xff1a; MySQL&#xff1a;是在数据库更新或者重启&#xff0c;则会丢失数据。 Oracle&#xff1a;把提交的sql操作线写入了在线联机日志文件中&#xff0c;保持到了磁盘上&#xff0c;可以随时恢复。 SqlServer&#xff1a;2…...

Java+Maven+GDAL

下载已经编译好的压缩包&#xff0c;下载地址 解压 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、查字典&#xff08;二分查找算法&#xff09;1.2、整理扑克&#xff08;插入排序算法&#xff09;1.3、货币找零&#xff08;贪心算法&#xff09; 2、算法与数据结构2.1、算法定义2.2、数据结构定义2.3、数据结构与算法的关系2.4、独立于编程语言…...

【Go】Go Gorm 详解

1. 概念 Gorm 官网&#xff1a;https://gorm.io/zh_CN/docs/ Gorm&#xff1a;The fantastic ORM library for Golang aims to be developer friendly&#xff0c;这是官网的介绍&#xff0c;简单来说 Gorm 就是一款高性能的 Golang ORM 库&#xff0c;便于开发人员提高效率 那…...

【IDEA版本升级JDK21报错方法引用无效 找不到符号】

java: 方法引用无效 找不到符号 符号: 方法 getFirst() 位置: 接口 java.util.List 升级JDK21版本遇到问题&#xff0c;报错找不到符号 但是点进去又能发现这个函数&#xff0c;证明能够找到这个方法&#xff0c;但是就是报错 java: 方法引用无效 找不到符号 符号: …...

2024 CKA模拟系统制作 | Step-By-Step | 17、题目搭建-排查故障节点

目录 免费获取题库配套 CKA_v1.31_模拟系统 一、题目 二、考点分析 1. Kubernetes 节点状态诊断 2. 节点故障修复技能 3. 持久化修复方案 4. SSH 特权操作 三、考点详细讲解 1. 节点状态机制详解 2. 常见故障原因深度分析 3. 永久修复技术方案 四、实验环境搭建步骤…...

亚远景-ISO 21434标准:汽车网络安全实践的落地指南

一、ISO 21434标准概述 ISO 21434是针对道路车辆网络安全的国际标准&#xff0c;旨在确保汽车组织在车辆的整个生命周期内采用结构化方法进行网络安全风险管理。 该标准适用于参与车辆开发的所有利益相关者&#xff0c;包括OEM、一级和二级供应商、汽车软件供应商以及网络安全…...

【高频面试题】数组中的第K个最大元素(堆、快排进阶)

文章目录 数组中的第K个最大元素题目描述示例1示例2提示&#xff1a; 解法1&#xff08;堆维护前k大元素&#xff09;解法2 手写堆维护解法3&#xff08;快速选择算法&#xff09;例题&#xff1a;P1923 【深基9.例4】求第 k 小的数参考 数组中的第K个最大元素 题目描述 给定…...

Web3怎么开发类似MetaMask的钱包

开发一个类似MetaMask的钱包&#xff0c;关键就是要利用以太坊提供的官方接口和标准&#xff0c;主要涉及以下几点&#xff1a; 1. 你要用到的以太坊官方接口和规范 JSON-RPC API 以太坊节点&#xff08;如Geth、OpenEthereum等&#xff09;通过JSON-RPC接口暴露各种功能&…...

榕壹云医疗服务系统:基于ThinkPHP+MySQL+UniApp的多门店医疗预约小程序解决方案

在数字化浪潮下,传统医疗服务行业正面临效率提升与客户体验优化的双重挑战。针对口腔、美容、诊所、中医馆、专科医院及康复护理等需要预约或诊断服务的行业,我们开发了一款基于ThinkPHP+MySQL+UniApp的多门店服务预约小程序——榕壹云医疗服务系统。该系统通过模块化设计与开…...

YOLO使用SAHI进行小目标检测

目录 一、环境配置二、使用ultralytics的YOLO模型进行训练和推理三、推理可视化的两种方法四、使用SAHI和ultralytics 训练的YOLO模型进行推理一、环境配置 下面是环境的配置过程,根据代码复杂度可以额外安装其他包。 #创建虚拟环境 conda create -n 环境名 python=3.9 #开启…...

NSSCTF [NISACTF 2022]ezheap

2058.[NISACTF 2022]ezheap(堆溢出) [NISACTF 2022]ezheap 1.准备 2.ida分析 main函数 int __cdecl main(int argc, const char **argv, const char **envp) {char *command; // [esp8h] [ebp-10h]char *s; // [espCh] [ebp-Ch]setbuf(stdin, 0);setbuf(stdout, 0);s (cha…...

完整解析 Linux Kdump Crash Kernel 工作原理和实操步骤

完整解析 Linux Kdump Crash Kernel 工作原理和实操步骤 一、前言 在使用 Linux 操作系统进行内核开发或者系统维护时&#xff0c;内核 panic 是最常见的系统崩溃环节。如果想要在内核崩溃后立即分析环境和输出内核内存 dump&#xff0c;Kdump crashkernel 是最接近完美的解…...

12-后端Web实战(登录认证)

在前面的课程中&#xff0c;我们已经实现了部门管理、员工管理的基本功能&#xff0c;但是大家会发现&#xff0c;我们并没有登录&#xff0c;就直接访问到了Tlias智能学习辅助系统的后台。 这是不安全的&#xff0c;所以我们今天的主题就是登录认证。最终要实现的效果是&#…...

汽配快车道:助力汽车零部件行业的产业重构与数字化出海

汽配快车道&#xff1a;助力汽车零部件行业的数字化升级与出海解决方案。 在当今快速发展的汽车零部件市场中&#xff0c;随着消费者对汽车性能、安全和舒适性的要求不断提高&#xff0c;汽车刹车助力系统作为汽车安全的关键部件之一&#xff0c;其市场需求也在持续增长。汽车…...