ReactHooks大全—useState

React Hooks是React 16.8版本引入的一种新的编程范式,它可以让我们在不使用class的情况下,使用state和其他React特性,。React Hooks的出现,不仅提高了函数组件的功能和复用性,也简化了组件的编写和维护,让我们的代码更加清晰和优雅。本文将详细介绍useState基本使用、工作原理以及最佳实践。

在这篇博文中,我将重点介绍useState这个Hook,它可以让你在函数组件中定义和更新状态。我将从基本用法开始,然后逐步深入探讨它的工作原理和一些最佳实践。

useState的基本用法

公众号:Code程序人生,个人网站:https://creatorblog.cn

useStateReact提供的一个内置Hook,它接受一个参数作为初始状态,返回一个包含两个元素的数组。第一个元素是当前状态,第二个元素是一个更新状态的函数。我们可以用数组解构的语法来获取这两个元素,并给它们取任意的名字。例如:

import React, { useState } from 'react';function Counter() {// 定义一个名为count的状态,初始值为0const [count, setCount] = useState(0);// 定义一个点击事件的处理函数,调用setCount来增加count的值function handleClick() {setCount(count + 1);}// 返回一个包含显示count和一个按钮的JSX元素return (<div><p>当前计数:{count}</p><button onClick={handleClick}>点击+1</button></div>);
}

上面的代码定义了一个简单的计数器组件,它使用useState来管理一个名为count的状态。每次点击按钮时,都会调用setCount函数,传入一个新的状态值,这会触发组件的重新渲染,显示最新的count值。

注意,useState的参数只会在组件的初始渲染时被使用,之后的渲染会忽略它,直接使用当前的状态值。因此,如果你想要动态地设置初始状态,你可以传入一个函数作为参数,这个函数会在初始渲染时被调用,返回一个状态值。例如:

// 假设有一个从localStorage中获取数据的函数
function getDataFromLocalStorage(key) {// 省略具体实现
}function Counter() {// 使用函数来设置初始状态,从localStorage中获取上次保存的计数值const [count, setCount] = useState(() => getDataFromLocalStorage('count') || 0);// 其他代码不变
}

useState的工作原理

要理解useState的工作原理,我们需要了解一些React的基本概念,如组件、元素、渲染和调和。

  • 组件是React的构建块,它是一个函数或一个类,接受一些输入(称为props),返回一个描述用户界面的输出(称为元素)。
  • 元素是React的最小单位,它是一个普通的JavaScript对象,描述了一个DOM节点或一个组件的类型、属性和子元素。
  • 渲染是React的核心功能,它是将元素转换为真实的DOM节点或组件实例的过程,也是触发组件生命周期和副作用的时机。
  • 调和是React的优化策略,它是在渲染时比较新旧元素的差异,只更新变化的部分,提高渲染效率的过程。

React中,当一个组件被渲染时,它会创建一个新的元素,并与上一次渲染的元素进行比较,如果有变化,就会更新对应的DOM节点或组件实例。这意味着,每次渲染都会产生一个新的元素,而不是修改原来的元素。这就是为什么React的元素是不可变的,一旦被创建,就不能被改变。

那么,如果元素是不可变的,状态又是如何被更新的呢?这就是useState的作用,它可以让我们在不可变的元素中保存和更新可变的状态。

useState的实现原理是使用了一个数组来存储所有的状态值和更新函数,每个状态对应一个固定的索引。当我们调用useState时,它会根据当前的索引,返回对应的状态值和更新函数,并将索引加一。

当我们调用更新函数时,它会接收一个新的状态值,并触发组件的重新渲染,这时useState会根据索引,返回最新的状态值和更新函数。

为了保证每个状态的索引不变,我们需要遵守一些规则:

  • 只在组件的顶层调用useState,不要在循环、条件或嵌套函数中调用。
  • 只在React函数中调用useState,不要在普通的JavaScript函数中调用。

useState的最佳实践

在使用useState时,有一些最佳实践可以帮助我们编写更好的代码,下面列举了一些常见的建议:

  • 为每个状态使用单独的useState,而不是将所有状态放在一个对象中。这样可以避免不必要的渲染,因为每次更新对象时,都会产生一个新的引用,导致React认为状态发生了变化,即使实际上没有变化。如果你需要将多个状态放在一个对象中,你可以使用useReducer来代替useState,它可以让你更好地管理复杂的状态逻辑。
  • 使用函数式更新,而不是直接依赖于旧的状态值。这样可以避免出现状态不一致的问题,因为在某些情况下,React可能会批量处理多个状态更新,导致旧的状态值不是最新的。如果你的新状态值依赖于旧的状态值,你可以传入一个函数作为参数,这个函数会接收旧的状态值,并返回新的状态值。例如:
// 不推荐的写法,直接依赖于旧的状态值
setCount(count + 1);// 推荐的写法,使用函数式更新,避免状态不一致
setCount(prevCount => prevCount + 1);
  • 使用惰性初始化,而不是在每次渲染时都计算初始状态。如果你的初始状态需要一些复杂的计算,你可以传入一个函数作为参数,这个函数会在初始渲染时被调用,返回一个状态值。这样可以避免在后续的渲染中重复计算,提高性能。例如:
// 不推荐的写法,每次渲染都会计算初始状态
const [data, setData] = useState(computeExpensiveValue());// 推荐的写法,使用惰性初始化,只在初始渲染时计算初始状态
const [data, setData] = useState(() => computeExpensiveValue());
  • 使用自定义Hook,而不是在组件中直接使用useState。如果你有一些通用的状态逻辑,你可以将它们封装在一个自定义Hook中,然后在不同的组件中复用。这样可以让你的组件更简洁,更易于维护。例如,你可以创建一个自定义Hook,用来获取和设置localStorage中的数据:
// 定义一个自定义Hook,接受一个键作为参数,返回一个包含数据和更新函数的数组
function useLocalStorage(key) {// 从localStorage中获取数据,如果没有则返回nullconst [data, setData] = useState(() => JSON.parse(localStorage.getItem(key)) || null);// 定义一个更新函数,接受一个新的数据,将其保存到localStorage中,并更新状态function updateData(newData) {// 将新的数据转换为字符串,保存到localStorage中localStorage.setItem(key, JSON.stringify(newData));// 调用setData,更新状态setData(newData);}// 返回一个包含数据和更新函数的数组return [data, updateData];
}// 在组件中使用自定义Hook,传入一个键,获取和设置localStorage中的数据
function Counter() {// 使用自定义Hook,传入'count'作为键,获取和设置localStorage中的计数值const [count, setCount] = useLocalStorage('count');// 其他代码不变
}

总结

useStateReact Hooks的一个重要部分,它可以让我们在函数组件中定义和更新状态,使得函数组件具有了类组件的能力。在使用useState时,我们需要注意以下几点:

  • useState接受一个参数作为初始状态,返回一个包含两个元素的数组,第一个元素是当前状态,第二个元素是一个更新状态的函数。
  • useState的参数只会在组件的初始渲染时被使用,之后的渲染会忽略它,直接使用当前的状态值。如果我们想要动态地设置初始状态,我们可以传入一个函数作为参数,这个函数会在初始渲染时被调用,返回一个状态值。
  • useState的工作原理是使用了一个数组来存储所有的状态值和更新函数,每个状态对应一个固定的索引。当我们调用useState时,它会根据当前的索引,返回对应的状态值和更新函数,并将索引加一。当我们调用更新函数时,它会接收一个新的状态值,并触发组件的重新渲染,这时useState会根据索引,返回最新的状态值和更新函数。
  • 为了保证每个状态的索引不变,我们需要遵守一些规则:只在组件的顶层调用useState,不要在循环、条件或嵌套函数中调用;只在React函数中调用useState,不要在普通的JavaScript函数中调用。
  • 在使用useState时,有一些最佳实践可以帮助我们编写更好的代码:为每个状态使用单独的useState,而不是将所有状态放在一个对象中;使用函数式更新,而不是直接依赖于旧的状态值;使用惰性初始化,而不是在每次渲染时都计算初始状态;使用自定义Hook,而不是在组件中直接使用useState。

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

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

相关文章

Spring 依赖查找知识点总结

前言 源码在我github的guide-spring仓库中&#xff0c;可以克隆下来 直接执行。 我们本文主要来介绍依赖查找的使用示例 依赖查找 什么是依赖查找 依赖查找并不是 Spring 框架特有的概念&#xff0c;它是一种在软件开发中获取依赖对象的方式。它通常用于获取运行时需要的服…

The Grid – Responsive WordPress Grid响应式网格插件

点击阅读The Grid – Responsive WordPress Grid响应式网格插件原文 The Grid – Responsive WordPress Grid响应式网格插件是一个高级 wordpress 网格插件&#xff0c;它允许您在完全可定制且响应迅速的网格系统中展示任何自定义帖子类型。 Grid WordPress 非常适合展示您的博…

QT信号、槽机制介绍与实现

时间记录&#xff1a;2023/12/17 1.介绍 QT中进行对象之间事件的处理机制为信号、槽机制&#xff0c;即一个对象状态改变时发出信号&#xff0c;然后与此信号进行绑定的对应槽便会被触发&#xff0c;类似于c/c里面的回调函数机制 2.信号 在一定情况下被发射的事件&…

【TB作品】51单片机,语音出租车计价器

西交大题目 1.语音出租车计价器 一、功能要求: 1.具有可模拟出租车车轮转速传感器的硬件设计,可计量出租车所走的公 里数。 2.显示和语音播报里程、价格和等待红灯或堵车的计时价格: 3.具有等待计时功能 4.具有实时年月日显示和切换功能。 5.操作简单、界面友好。 二、设计建议…

08-工厂方法

意图 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类 类图 适用性 在下列情况可以使用工厂方法模式&#xff1a; 当一个类不知道它所必须创建的对象的类的时候。当一个类希望由它的子类来指定它所创建的对象的时候。当类将创建对象的职责委托给多个帮助子…

PCL 已知同名点对计算旋转矩阵并对点云进行旋转

目录 一、 算法概述二、代码实现三、测试示例一、 算法概述 适用:已知三组及三组以上的同名点对,计算旋转矩阵;然后根据旋转矩阵对点云进行旋转,最后保存旋转后的点云文件。 二、代码实现 #include <Eigen/Core> #include <Eigen/Dense>

c++程序设计定义一个MyString类,实现两个字符串连接。要求定义类的数据成员为字符指针,实现深拷贝函数。

定义一个MyString类&#xff0c;实现两个字符串连接。要求定义类的数据成员为字符指针&#xff0c;实现深拷贝函数。 要求&#xff1a;不能使用<string>,可以使用<cstring>中的 strcpy 、strcat、strcmp以及strlen( )等函数 已知测试函数如下&#xff1a; int m…

持久化存储 StorageClass

kubernetes从v1.4版本开始引入了一个新的资源对象StorageClass&#xff0c;用于标记存储资源的特性和性能。到v1.6版本时&#xff0c;StorageClass和动态资源供应的机制得到了完善&#xff0c;实现了存储卷的按需创建&#xff0c;在共享存储的自动化管理进程中能够实现了重要的…

ELK(八)—Metricbeat部署

目录 介绍修改配置文件启动 Modulenginx开启状态查询配置Nginx module查看是否配置成功 介绍 Metricbeat 是一个轻量级的开源度量数据收集器&#xff0c;用于监控系统和服务。它由 Elastic 公司开发&#xff0c;并作为 Elastic Stack&#xff08;Elasticsearch、Logstash、Kiba…

【Linux】在vim中批量注释与批量取消注释

在vim编辑器中&#xff0c;批量注释和取消注释的操作可以通过进入V-BLOCK模式、选择要注释或取消注释的内容、输入注释符号或选中已有的注释符号和按键完成。这些操作可以大大提高代码或文本的编写和修改效率&#xff0c;是vim编辑器中常用的操作之一。 1.在vim中批量注释的步…

[elementPlus] teleported 在 ElSubMenu中的用途

如图 一个菜单对应的路由结构如上图 如果做适配窄屏幕 如果在 <ElSubMenu :index"route.path" >中不加入 teleported 就会出现问题 加上就OK了 <ElSubMenu :index"route.path" teleported>

力扣200. 岛屿数量(java DFS解法)

Problem: 200. 岛屿数量 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 该问题可以归纳为一类遍历二维矩阵的题目&#xff0c;此类中的一部分题目可以利用DFS来解决&#xff0c;具体到本题目&#xff1a; 1.我们首先要针对于二维数组上的每一个点&#xff0c;尝试展…

单片机期末复习

前言 发现很多人都写了单片机原理及接口技术课后习题的答案&#xff0c;但是也就只写了答案而已&#xff0c;可能是他们觉得太简单的缘故吧&#xff0c;我这里对此进行一下我近段时间复习的总结&#xff0c;本篇博客只展示选择题、填空题和判断题的答案&#xff0c;仅供参考&a…

饥荒Mod 开发(十一):修改物品堆叠

饥荒Mod 开发(十)&#xff1a;制作一把AOE武器 饥荒Mod 开发(十二)&#xff1a;一键制作 饥荒中物品栏有限&#xff0c;要拾取的物品有很多&#xff0c;经常装不下要忍痛丢掉各种东西&#xff0c;即使可以将物品放在仓库但是使用不方便&#xff0c;所以可以将物品的堆叠个数设…

1264. 动态求连续区间和(树状数组---某个位置加上一个数/求在线(动态)前缀和/蓝桥杯)

题目&#xff1a; 输入样例&#xff1a; 10 5 1 2 3 4 5 6 7 8 9 10 1 1 5 0 1 3 0 4 8 1 7 5 0 4 8输出样例&#xff1a; 11 30 35 树状数组&#xff1a; 代码&#xff1a; #include<cstdio> #include<iostream> using namespace std;const int N100010; int n,…

系统架构设计师教程(七)系统架构设计基础知识

系统架构设计基础知识 7.1 软件架构概念7.1.1 软件架构的定义7.1.2 软件架构设计与生命周期需求分析阶段设计阶段实现阶段构件组装阶段部署阶段后开发阶段 7.1.3 软件架构的重要性 7.2 基于架构的软件开发方法7.2.1 体系结构的设计方法概述7.2.2 概念与术语7.2.3 基于体系结构的…

Autosar通信实战系列07-Com模块要点及其配置介绍(二)

本文框架 前言1. ComGeneral配置2. ComConfig配置2.1 ComGwMapping2.2 ComIPdus2.3 ComIPduGroups2.4 ComIPduSignals2.5 ComIPduSignalGroups2.6 ComTimeBasis前言 在本系列笔者将结合工作中对通信实战部分的应用经验进一步介绍常用,包括但不限于通信各模块的开发教程,代码…

基于sfunction builder的c-sfunction编写及案例测试分析

目录 前言 1.前期准备工作及文件说明 1.1前期准备工作 1.2 文件说明 1.3 编译方式

深度剖析JavaScript中冒泡和捕获机制、事件代理

JS事件传播的两种机制包括冒泡和捕获&#xff0c;下面将具体剖析它们之间本质的区别。 事件冒泡: 先触发子元素的事件&#xff0c;再触发父元素的事件。 创建一个 ul label 和 li label, 分别绑定一个父id 和 子 id, 再通过创建 script&#xff0c;去绑定各自的点击事件。 <…

阿里云|人工智能(AI)技术解决方案

函数计算部署Stable Diffusion AI绘画技术解决方案 通过函数计算快速部署Stable Diffusion模型为用户提供快速通过文字生成图片的能力。该方案通过函数计算快速搭建了AIGC的能力&#xff0c;无需管理服务器等基础设施&#xff0c;专注模型的能力即可。该方案具有高效免运维、弹…