图文并茂教你快速入门React系列02-state

news2024/11/24 13:05:22

State

在React中,什么是state?

在 React 中,随时间变化的数据被称为状态(state)。你可以向任何组件添加状态,并按需进行更新。

如何添加使用state?

  • 点击获取教程代码
  • 关于此框架–More docs

使用 useState Hook 为组件添加状态

例如

import { useState } from 'react';
const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);

state特别之处

新的(奇怪的)知识要增加了~ 下面会做解释哦~

  • 与普通 JavaScript 变量不同,React state的行为更像一个快照。设置它并不改变你已有的状态变量,而是触发一次重新渲染。
  • 通俗来说,就是临时的,一次性的那种,第一次看到这个说实话我也很惊讶
  • 官方文档是这么解释的:React 这样工作是为了帮助你避免微妙的 bug。

举个栗子

console.log(count);  // 0
setCount(count + 1); // 请求用 1 重新渲染
console.log(count);  // 仍然是 0!

为什么出现这个问题?如何解决这个问题?

原因:一个 state 变量的值在 React 通过调用你的组件“获取 UI 的快照”时就被“固定”了, 即使其事件处理函数的代码是异步的。
解决:set的时候传入函数就OK了,举例如下

setScore(s => s + 1)

更新 state 后替换 state ,会如何运行呢?

import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 5);
        setNumber(n => n + 1);
        setNumber(42);
      }}>增加数字</button>
    </>
  )
}

答案如下:

注意事项

  • 在严格模式下,React 会执行每个更新函数两次(但是丢弃第二个结果)以便帮助你发现错误。

useState Hook 功能

  • 在 React 中,useState 以及任何其他以“use”开头的函数都被称为 Hook。
  • State 变量 用于保存渲染间的数据。
  • State setter 函数 更新变量并触发 React 再次渲染组件。
  • 渲染同一个组件两次,每个副本都会有完全隔离的 state,改变其中一个不会影响另一个。

用法

对于下面代码来说:index 是一个 state 变量,setIndex 是对应的 setter 函数。

import { useState } from 'react';

const [index, setIndex] = useState(0);

使用state 处理对象和数组的数据变化

  • 创建一个新的对象(或复制现有的对象),然后用这个副本来更新状态
  • 使用 … 展开语法来复制你想改变的对象和数组

举个栗子

import { useState } from 'react';

export default function Form() {
  const [person, setPerson] = useState({
    name: 'Niki de Saint Phalle',
    artwork: {
      title: 'Blue Nana',
      city: 'Hamburg',
      image: 'https://i.imgur.com/Sd1AgUOm.jpg',
    }
  });

  function handleNameChange(e) {
    setPerson({
      ...person,
      name: e.target.value
    });
  }

  function handleTitleChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        title: e.target.value
      }
    });
  }

  function handleCityChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        city: e.target.value
      }
    });
  }

  function handleImageChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        image: e.target.value
      }
    });
  }

  return (
    <>
      <label>
        Name:
        <input
          value={person.name}
          onChange={handleNameChange}
        />
      </label>
      <label>
        Title:
        <input
          value={person.artwork.title}
          onChange={handleTitleChange}
        />
      </label>
      <label>
        City:
        <input
          value={person.artwork.city}
          onChange={handleCityChange}
        />
      </label>
      <label>
        Image:
        <input
          value={person.artwork.image}
          onChange={handleImageChange}
        />
      </label>
      <p>
        <i>{person.artwork.title}</i>
        {' by '}
        {person.name}
        <br />
        (located in {person.artwork.city})
      </p>
      <img
        src={person.artwork.image}
        alt={person.artwork.title}
      />
    </>
  );
}

试一把这个代码吧~~

Tips: 可以使用 Immer 之类的库来减少重复代码

import { useImmer } from 'use-immer';

export default function Form() {
  const [person, updatePerson] = useImmer({
    name: 'Niki de Saint Phalle',
    artwork: {
      title: 'Blue Nana',
      city: 'Hamburg',
      image: 'https://i.imgur.com/Sd1AgUOm.jpg',
    }
  });

  function handleNameChange(e) {
    updatePerson(draft => {
      draft.name = e.target.value;
    });
  }

  function handleTitleChange(e) {
    updatePerson(draft => {
      draft.artwork.title = e.target.value;
    });
  }

  function handleCityChange(e) {
    updatePerson(draft => {
      draft.artwork.city = e.target.value;
    });
  }

  function handleImageChange(e) {
    updatePerson(draft => {
      draft.artwork.image = e.target.value;
    });
  }

  return (
    <>
      <label>
        Name:
        <input
          value={person.name}
          onChange={handleNameChange}
        />
      </label>
      <label>
        Title:
        <input
          value={person.artwork.title}
          onChange={handleTitleChange}
        />
      </label>
      <label>
        City:
        <input
          value={person.artwork.city}
          onChange={handleCityChange}
        />
      </label>
      <label>
        Image:
        <input
          value={person.artwork.image}
          onChange={handleImageChange}
        />
      </label>
      <p>
        <i>{person.artwork.title}</i>
        {' by '}
        {person.name}
        <br />
        (located in {person.artwork.city})
      </p>
      <img
        src={person.artwork.image}
        alt={person.artwork.title}
      />
    </>
  );
}

Immer处理数组

import { useState } from 'react';
import { useImmer } from 'use-immer';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [list, updateList] = useImmer(initialList);

  function handleToggle(artworkId, nextSeen) {
    updateList(draft => {
      const artwork = draft.find(a =>
        a.id === artworkId
      );
      artwork.seen = nextSeen;
    });
  }

  return (
    <>
      <h1>Art Bucket List</h1>
      <h2>My list of art to see:</h2>
      <ItemList
        artworks={list}
        onToggle={handleToggle} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

小伙伴们,先写到这里啦,我们明天再见啦~~

大家要天天开心哦

欢迎大家指出文章需要改正之处~
学无止境,合作共赢

在这里插入图片描述

欢迎路过的小哥哥小姐姐们提出更好的意见哇~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/599743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记一次Redis版本新特性导致的主从切换故障

背景 最近一组业务redis数据不断增长需要扩容内存&#xff0c;而扩容内存则需要重启云主机&#xff0c;在按计划扩容升级执行主从切换时意外发生了数据丢失与master进入只读状态的故障&#xff0c;这里记录分享一下。 业务redis高可用架构 该组业务redis使用的是一主一从&am…

基于卷积神经网络和连接性时序分类的语音识别系统,含核心Python工程源代码(深度学习)个人可二次开发

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 特征提取2. 声学模型3. CTC 解码4. 语言模型 系统测试工程源代码下载其它资料下载 前言 本项目基于卷积神经网络和连接性时序分类方法&#xff0c;采用中文语音数据集进行训练&#xff0c;实现声音转录为中文拼…

Java枚举中定义属性

文章目录 1、复习枚举2、自定义属性3、自定义属性枚举类和常量的对比4、常用方法5、枚举自定义属性在开发中的应用&#xff1a;字典表6、补充&#xff1a;入参校验 刚接触枚举时的例子太简单&#xff0c;就一个Season枚举类&#xff0c;里面四个常量值&#xff0c;后来开发中看…

接口幂等方案

文章目录 概要方案乐观锁数据库唯一索引令牌tokentoken通过另一个接口从服务端获取客户端自身生成token 总结 概要 所谓接口幂等性&#xff0c;就是一次和多次请求某一个资源对于资源本身应该具有同样的影响。接口幂等的应用很广&#xff0c;小到防止表单重复提交&#xff0c;…

使用kettle完成学生成绩登记需求

&#xff08;一&#xff09; 使用kettle完成学生成绩登记需求 学生成绩表下表所示。(自己创建一个学生表) 在MySQL中创建一个名为school的数据库&#xff0c;并在school数据库中创建一个名为score的表&#xff0c;使用Kettle将Excel形式的学生成绩表导入MySQL的score表 1&am…

机器视觉海康工业相机SDK参数设置获取

视觉人机器视觉培训-缺陷检测项目-食品行业草鸡蛋外观检测 相机参数类型可分为六类,除 command 参数外,每一类都有其对应的设置与获取函数接口。 表 1 参数类型及对应函数接口介绍 *详细函数接口可参考 SDK 手册: ​C:\Program Files (x86)\MVS\Development\Documentation…

【已解决】微信小程序报错:request 合法域名校验出错 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“详情-域名信息”

【已解决】微信小程序报错&#xff1a;request 合法域名校验出错 如若已在管理后台更新域名配置&#xff0c;请刷新项目配置后重新编译项目&#xff0c;操作路径&#xff1a;“详情-域名信息” 场景复现解决方法 知识专栏专栏链接微信小程序专栏https://blog.csdn.net/xsl_hr/c…

工控设备如何防勒索病毒

目前现状 无论是中小企业还是大型企事业单位&#xff0c;均有属于自己的内网或公有云服务器。这些服务器有的是专门的SVN、GIT代码服务器&#xff0c;有的是文档存储服务器&#xff0c;有的是应用服务器。服务器是企业的核心命脉&#xff0c;所有知识产权及多年心血都集中汇总…

LeetCode——Pow(x, n)

一、题目 50. Pow(x, n) - 力扣&#xff08;Leetcode&#xff09; 实现 pow(x, n) &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即&#xff0c;xⁿ &#xff09;。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;1024.00000示例 2&#x…

Jetpack Compose中的状态栏适配(Window Insets)

除了app的内容区域外&#xff0c;还有一些其他的固定元素会显示在手机屏幕上&#xff0c;顶部的状态栏、 刘海、 底部的导航栏&#xff0c;还有输入法键盘&#xff0c;它们都是系统的UI&#xff0c; 也叫Insets. 如图所示: 顶部的状态栏通常被用来展示通知, 设备状态等; 底部导…

软考A计划-网络规划设计师-学习笔记-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Linux 如何判断文件的类型

在Linux中&#xff0c;我们如何判断一个文件的类型和用户权限呢&#xff1f; 在c语言中&#xff0c;Linux为我们提供了一个结构体stat我们可以通过 #include<sys/stat.h>引入后使用。然后通过stat中的st_mode来判断文件的类型。如下图&#xff0c;我们要知道文件是什么类…

超级入门:R 语言的 5 种基本数据类型

一、R语言简介 R语言是一种用于统计计算和绘图的编程语言&#xff0c;它是由新西兰奥克兰大学的 Ross Ihaka 和 Robert Gentleman 开发的。R语言支持向量和矩阵计算&#xff0c;因此也可以用于数值分析和线性代数。它主要应用于数据分析、统计学习、数据挖掘、数据可视化等领域…

【Springboot】集成QQ邮箱信息发送

系列文章目录 文章目录 系列文章目录前言添加Maven依赖QQ邮箱开启POP服务配置application.properties文件Controller层编写 vue前端&#xff08;也可以直接省略&#xff09; 前言 这篇博客用于简单实现SpringBoot中发送请求&#xff0c;用户可以收到邮件。 添加Maven依赖 <…

ISIS 实验

(1)拓扑图 2&#xff09;需求&#xff1a; -实现PC1和PC2的通信 3&#xff09;配置步骤&#xff1a; -配置接口IP地址 -开启ISIS---类似于在OSPF中创建进程 -配置NET地址---类似于在OSPF中创建区域&#xff0c;指定Router-id -在接口上启用ISIS--类似于在OSPFv2中用ne…

SKNet讲解

SKNet讲解 0. 引言1. 网络结构1.1 Split部分1.2 Fuse部分1.3 Select部分1.4 三分支的情况 2. SKNet网络体系结构3. 分析与解释4. 代码总结 0. 引言 视皮层神经元的感受野大小受刺激的调节&#xff0c;即对不同刺激&#xff0c;卷积核的大小应该不同&#xff0c;但在构建CNN时一…

<DB2>《DB2创建分区表及相关操作》(精华)

《DB2创建分区表及相关操作》 1 基本概念2 操作2.1 查看数据库中存在的分区表2.2 查看分区表详细2.3 断开对数据表的访问连接2.4 备份数据2.5 拆离分区2.6 添加分区2.7 导入数据2.8 校验前后数据2.9 删除临时表数据 1 基本概念 当表中的数据量不断增大&#xff0c;查询数据的速…

使用Kettle实现数据排序

一、Kettle的安装 1.下载Kettle的安装包文件 在Windows系统中打开浏览器&#xff0c;访问Kettle官网&#xff08;https://sourceforge.net/projects/pentaho/&#xff09;&#xff0c;下载Kettle安装文件pdi-ce-9.1.0.0-324.zip。 或者在我的百度网盘分享里面下载 链接&…

【软件测试】软件测试总结笔记(2)

软件测试过程&#xff08;内容&#xff09; 1.单元测试基本概念定义⭐单元测试环境⭐单元测试内容单元测试用例的设计思路⭐单元测试的过程 2. 集成测试集成测试内容集成测试优点⭐集成测试层次集成测试方法Drivers and Stubs ⭐集成策略&#xff08;基于分解的集成&#xff09…

crontab定时任务介绍

1 crontab概述 crontab是linux操作系统上用来设置定时任务的基础命令&#xff0c;是基于crond服务实现任务调度执行。 当安装完成操作系统后&#xff0c;默认会安装crond服务及其附属命令&#xff0c;并且会自动启动crond进程&#xff0c;crond进程每分钟会定期检查是否有要执…