React-Hooks useState,useEffect用法

2024-02-18 17:38

本文主要是介绍React-Hooks useState,useEffect用法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

定义

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

useState

通过在函数组件里调用它来给组件添加一些内部 state。useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。useState 唯一的参数就是初始 state。这个初始 state 参数只有在第一次渲染的时候会被用到。

使用useState可以声明多个state变量。

不使用useState的时候,我们会发现一个最麻烦的问题,就是要去维护this,因为我们知道,每一个class类的this,都是要从父组件继承的,本身是没有this的,所以需要使用constructor去初始化this。
而useState,让我们使用函数编程,我们之前写无状态组件的时候,用的就是函数编程,而使用useState之后,我们可以在函数编程里面使用状态。也就是说:count变成了函数里面的变量,setCount变成了函数里面的函数变量,那么使用的时候直接使用就行了,不再需要使用this
useState接收一个参数,返回的是一个数组,参数表示初始值,数组的第0项就是定义的变量,第1项就是改变变量的方法。
参数可以是基本数据类型,如string、number,也可以是复合数据类型,如array,object等,如下代码

import React, { useState } from 'react'
export default function App() {const [count, setCount] = useState(0)const [obj, setObj] = useState({name: "aaa"})const [arr, setArr] = useState([1,2,3])return (<div><div>{count}</div><button onClick={() => { setCount(count + 1) }}>add</button><div>{obj.name}---{obj.age}</div><button onClick={() => { setObj({...obj,age: 20,name: "bbb"}) }}>add</button>{arr.map(item => {return <div>{item}</div>})}<button onClick={() => { setArr([...arr, 4]) }}>add</button></div>)
}

基本数据类型,可以直接修改,而复合数据类型,需要先通过解构运算符,然后再设置成新的复合数据类型。 

useEffect

useEffect (副作用函数)是一个 Effect Hook,给函数组件增加了操作副作用(在 React 组件中进行数据获取、订阅或者手动修改 DOM等)的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API,默认情况下,React 会在每次渲染后调用副作用函数 ,包括第一次渲染的时候。

通过使用 Hook,你可以把组件内相关的副作用组织在一起(例如创建订阅及取消订阅),而不要把它们拆分到不同的生命周期函数里。

useEffect接收一个函数作为参数,会在页面加载完成的时候以及数据更新的时候,触发执行。

上面实例每次重新渲染都要执行一遍useEffect,如果你在useEffect中使用了useState则会导致无限循环,这样显然是影响性能的。为了处理这个问题,我们可以给useEffect传第二个参数。用第二个参数来告诉react只有当这个参数的值发生改变时,才执行我们传的副作用函数(即第一个参数)。

当我们第二个参数传一个空数组[]时,相当于只在首次渲染的时候执行。

import React,{Component, useState,useEffect} from 'react'
import './App.css';class App2 extends Component{state = {count:0,size:{width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,}}onResize=()=>{this.setState({size:{width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,}})}componentDidMount(){document.title = this.state.count;window.addEventListener('resize',this.onResize);}componentWillUnmount(){window.removeEventListener('resize',this.onResize);}componentDidUpdate(){document.title = this.state.count;}render(){const {count,size} = this.state;return (<button type="button" onClick={()=>{this.setState({count:count+1})}}>click{count}size:{size.width}*{size.height}</button>);}
}function App(props) {// const [count,setCount] = useState(()=>{//   //提供一个函数,提高初始效率//   return props.defaultCount||0// });const [count,setCount] = useState(0);const [size,setSize] = useState({width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,})const onResize = ()=>{setSize({width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,})}useEffect(()=>{    //我们传递了第二个参数为一个空数组,它表示不监听任何数值,那么useEffect就只会在页面加载完成的时候触发一次,而count更新的时候不会触发。如果想要count更新的时候触发,则在数组内添加参数console.log('count',count)},[count])//useEffect统一在渲染后调用useEffect(()=>{   //didmount,didupdatedocument.title = count;})//每次渲染后都运行,加一个【】,绑定的函数只会发生在第一次渲染后,并且在组件卸载之前才会运行绑定函数
//我们都知道定时器在页面销毁的时候,需要清除,我们一般都会在componentUnMount,页面销毁的时候去把定时器清除,那么使用useEffect是如何清除呢?其实很简单,只需要在第一个参数的函数里面,return一个函数,函数里面写清除的方法就行了。这样在页面被卸载的时候,就会把定时器清除useEffect(()=>{    //didmount,willUnmountwindow.addEventListener('resize',onResize);return ()=>{window.removeEventListener('resize',onResize);}},[])const onClick=()=>{console.log('click');}useEffect(()=>{  document.querySelector('#size').addEventListener('click',onClick,false)return ()=>{  //清理状态,获取最新状态document.querySelector('#size').removeEventListener('click',onClick,false)}})return (<><button type="button" onClick={()=>{setCount(count+1)}}>click{count}</button>{count%2?<span id="size">size:{size.width}*{size.height}</span>:<p id="size">size:{size.width}*{size.height}</p>}</>);
}export default App;

//在使用useEffext处理title和size的时候,写了两个useEffect,不同的逻辑做不同的事情,这就是关注点分离

// 1、提高了组件复用

// 2、优化了关注点分离

// 两个函数的区别在于第二个参数,空数组,是精髓,只有数组的每一项都不变,所以只有第一次被渲染的时候才会被调用

 

 

 

这篇关于React-Hooks useState,useEffect用法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/721929

相关文章

全面掌握 SQL 中的 DATEDIFF函数及用法最佳实践

《全面掌握SQL中的DATEDIFF函数及用法最佳实践》本文解析DATEDIFF在不同数据库中的差异,强调其边界计算原理,探讨应用场景及陷阱,推荐根据需求选择TIMESTAMPDIFF或inte... 目录1. 核心概念:DATEDIFF 究竟在计算什么?2. 主流数据库中的 DATEDIFF 实现2.1

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Java中的数组与集合基本用法详解

《Java中的数组与集合基本用法详解》本文介绍了Java数组和集合框架的基础知识,数组部分涵盖了一维、二维及多维数组的声明、初始化、访问与遍历方法,以及Arrays类的常用操作,对Java数组与集合相... 目录一、Java数组基础1.1 数组结构概述1.2 一维数组1.2.1 声明与初始化1.2.2 访问

MySQL 中的 CAST 函数详解及常见用法

《MySQL中的CAST函数详解及常见用法》CAST函数是MySQL中用于数据类型转换的重要函数,它允许你将一个值从一种数据类型转换为另一种数据类型,本文给大家介绍MySQL中的CAST... 目录mysql 中的 CAST 函数详解一、基本语法二、支持的数据类型三、常见用法示例1. 字符串转数字2. 数字

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

解读GC日志中的各项指标用法

《解读GC日志中的各项指标用法》:本文主要介绍GC日志中的各项指标用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基础 GC 日志格式(以 G1 为例)1. Minor GC 日志2. Full GC 日志二、关键指标解析1. GC 类型与触发原因2. 堆

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的