react之Hooks的介绍、useState与useEffect副作用的使用

这篇具有很好参考价值的文章主要介绍了react之Hooks的介绍、useState与useEffect副作用的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、Hooks的基本介绍

  • Hooks 是 React v16.8 中的新增功能
  • 为函数组件提供状态、生命周期等原本 class 组件中提供的 React 功能
  • 可以理解为通过 Hooks 为函数组件钩入 class 组件的特性
  • 注意:Hooks 只能在函数组件中使用,自此,函数组件成为 React 的新宠儿
  • 可以在项目中同时使用hooks和class

二、useState的使用

2.1 简单使用

  • 一个 Hook 就是一个特殊的函数,让你在函数组件中获取状态等 React 特性
  • useState使用场景:当你想要在函数组件中,使用组件状态时,就要使用 useState Hook 了
  • useState作用:为函数组件提供状态(state)
import { useState } from 'react'

const Count = () => {  
  // stateArray 是一个数组
  const stateArray = useState(0)

  const state = stateArray[0]
  const setState = stateArray[1]

  return (
    <div>
      {/* 展示状态值 */}
      <h1>状态为:{state}</h1>
      {/* 点击按钮,让状态值 +1 */}
      <button onClick={() => setState(state + 1)}>+1</button>
    </div>
  )
}

2.2 数组结构简化

import { useState } from 'react'

const Count = () => {
  // 解构:
  const [count, setCount] = useState(0)

  return (
    <div>
      <h1>计数器:{state}</h1>
      <button onClick={() => setState(state + 1)}>+1</button>
    </div>
  )
}

2.3 状态的读取和修改

  • 读取状态:useState 提供的状态,是函数内部的局部变量,可以在函数内的任意位置使用
const Counter = () => {
  const [user, setUser] = useState({ name: 'jack', age: 18 })
  
  return (
  	<div>
    	<p>姓名:{user.name}</p>
			<p>年龄:{user.age}</p>
    </div>
  )
}

修改状态:

  • setCount(newValue) 是一个函数,参数表示:新的状态值
    • 调用该函数后,将使用新的状态值替换旧值
    • 修改状态后,因为状态发生了改变,所以,该组件会重新渲染
const Counter = () => {
  const [user, setUser] = useState({ name: 'jack', age: 18 })
  
  const onAgeAdd = () => {
    setUser({
      ...user,
      age: user.age + 1
    })
  }
  
  return (
  	<div>
    	<p>姓名:{user.name}</p>
			<p>年龄:{user.age}</p>
     	<button onClick={onAgeAdd}>年龄+1</button>
    </div>
  )
}
  • 修改状态的时候,一定要使用新的状态替换旧的状态

2.3 组件的更新过程

函数组件使用 useState hook 后的执行过程,以及状态值的变化:

  • 组件第一次渲染:
    • 1.从头开始执行该组件中的代码逻辑
    • 2.调用 useState(0) 将传入的参数作为状态初始值,即:0
    • 3.渲染组件,此时,获取到的状态 count 值为: 0
  • 组件第二次渲染:
    • 1.点击按钮,调用 setCount(count + 1) 修改状态,因为状态发生改变,所以,该组件会重新渲染
    • 2.组件重新渲染时,会再次执行该组件中的代码逻辑
    • 3.再次调用 useState(0),此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 1
    • 4.再次渲染组件,此时,获取到的状态 count 值为:1
  • useState 的初始值(参数)只会在组件第一次渲染时生效

核心代码

import { useState } from 'react'

const Count = () => {
  const [count, setCount] = useState(0)

  return (
    <div>
      <h1>计数器:{count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  )
}

三、useEffect的使用

3.1 副作用介绍

内容:

  • 使用场景:当你想要在函数组件中,处理副作用(side effect)时,就要使用 useEffect Hook 了

  • 作用:处理函数组件中的副作用(side effect)

  • 问题:副作用(side effect)是什么?

  • 回答:在计算机科学中,如果一个函数或其他操作修改了其局部环境之外的状态变量值,那么它就被称为有副作用
    类比,对于 999 感冒灵感冒药来说:

  • (主)作用:用于感冒引起的头痛,发热,鼻塞,流涕,咽痛等

  • 副作用:可见困倦、嗜睡、口渴、虚弱感

  • 理解:副作用是相对于主作用来说的,一个功能(比如,函数)除了主作用,其他的作用就是副作用

  • 对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)

  • 常见的副作用(side effect):数据(Ajax)请求、手动修改 DOM、localStorage、console.log 操作等

总结

​ 对于react组件来说,除了渲染UI之外的其他操作,都可以称之为副作用

let a = 1

const Count = () => {
  const [count, setCount] = useState(0)

  const handleClick = () => {
    setCount(count + 1)
  }
  
  console.log('aaa')
  axios.post('http://xxx')
  localStorage.setItem()
  a = 2
  
  return (
    <div>
      <h1>计数器:{count}</h1>
      <button onClick={handleClick}>+1</button>
    </div>
  )
}

3.2 基本使用

  • 使用场景:当你想要在函数组件中,处理副作用(side effect)时就要使用 useEffect Hook 了

  • 作用:处理函数组件中的一些副作用(side effect)

  • 注意:在实际开发中,副作用是不可避免的。因此,react 专门提供了 useEffect Hook 来处理函数组件中的副作用

语法:

  • 参数:回调函数(称为 effect),就是在该函数中写副作用代码
  • 执行时机:该 effect 会在组件第一次渲染以及每次组件更新后执行
  • 相当于 componentDidMount + componentDidUpdate

核心代码

import { useEffect } from 'react'

const Counter = () => {
  const [count, setCount] = useState(0)
  
  useEffect(() => {
    document.title = `当前已点击 ${count}`
  })
  
  return (
  	<div>
    	<h1>计数器:{count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  )
}

3.3 依赖

内容:

  • 问题:如果组件中有另外一个状态,另一个状态更新时,刚刚的 effect 回调也会执行

  • 默认情况:只要状态发生更新 useEffect 的 effect 回调就会执行

  • 性能优化:跳过不必要的执行,只在 count 变化时,才执行相应的 effect

  • 语法:

    • 第二个参数:可选,也可以传一个数组,数组中的元素可以成为依赖项(deps)
    • 该示例中表示:只有当 count 改变时,才会重新执行该 effect

    核心代码

import { useEffect } from 'react'

const Counter = () => {
  const [count, setCount] = useState(0)
  const [loading, setLoading] = useState(false)
  
  useEffect(() => {
    document.title = `当前已点击 ${count}`
  }, [count])
  
  return (
  	<div>
    	<h1>计数器:{count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <button onClick={() => setLoading(!loading)}>切换 loading</button>
    </div>
  )
}

3.4 不要对依赖项撒谎

内容:

  • useEffect 回调函数(effect)中用到的数据(比如,count)就是依赖数据,就应该出现在依赖项数组中
  • 如果 useEffect 回调函数中用到了某个数据,但是,没有出现在依赖项数组中,就会导致一些 Bug 出现!
  • 所以,不要对 useEffect 的依赖撒谎
const App = () => {
  const [count, setCount] = useState(0)
  
  // 错误演示:
  useEffect(() => {
    document.title = '点击了' + count + '次'
  }, [])
  
  return (
    <div>
      <h1>计数器:{count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  )
}

useEffect完全指南:https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/

3.5 依赖项可以是空数组

内容

  • useEffect 的第二个参数,还可以是一个空数组([]),表示只在组件第一次渲染后执行 effect

  • 使用场景:1 事件绑定 2 发送请求获取数据 等

  • 语法:

    • 该 effect 只会在组件第一次渲染后执行,因此,可以执行像事件绑定等只需要执行一次的操作
    • 此时,相当于 class 组件的 componentDidMount 钩子函数的作用
useEffect(() => {
  const handleResize = () => {}
  window.addEventListener('resize', handleResize)
}, [])

注意:

  • 跟 useState Hook 一样,一个组件中也可以调用 useEffect Hook 多次
  • 推荐:一个 useEffect 只处理一个功能,有多个功能时,使用多次 useEffect

3.6 清理工作

内容:

  • effect 的返回值是可选的,可省略。也可以返回一个清理函数,用来执行事件解绑等清理操作
  • 清理函数的执行时机:
    • 清理函数会在组件卸载时以及下一次副作用回调函数调用的时候执行,用于清除上一次的副作用。
    • 如果依赖项为空数组,那么会在组件卸载时会执行。相当于组件的componetWillUnmount

核心代码:文章来源地址https://www.toymoban.com/news/detail-653840.html

useEffect(() => {
  const handleResize = () => {}
  window.addEventListener('resize', handleResize)
  
  // 这个返回的函数,会在该组件卸载时来执行
  // 因此,可以去执行一些清理操作,比如,解绑 window 的事件、清理定时器 等
  return () => window.removeEventListener('resize', handleResize)
}, [])

3.7 useEffect的 4 种使用使用方式

// 1
// 触发时机:1 第一次渲染会执行 2 每次组件重新渲染都会再次执行
// componentDidMount + ComponentDidUpdate
useEffect(() => {})

// 2(使用频率最高)
// 触发时机:只在组件第一次渲染时执行
// componentDidMount
useEffect(() => {}, [])

// 3(使用频率最高)
// 触发时机:1 第一次渲染会执行 2 当 count 变化时会再次执行
// componentDidMount + componentDidUpdate(判断 count 有没有改变)
useEffect(() => {}, [count])

// 4
useEffect(() => {
  // 返回值函数的执行时机:组件卸载时
  // 在返回的函数中,清理工作
  return () => {
  	// 相当于 componentWillUnmount
  }
}, [])

useEffect(() => {
  
  // 返回值函数的执行时机:1 组件卸载时 2 count 变化时
  // 在返回的函数中,清理工作
  return () => {}
}, [count])

3.8 发送请求

内容:

  • 在组件中,可以使用 useEffect Hook 来发送请求(side effect)获取数据

  • 注意:effect 只能是一个同步函数,不能使用 async

    • 因为如果 effect 是 async 的,此时返回值是 Promise 对象。这样的话,就无法保证清理函数被立即调用
  • 为了使用 async/await 语法,可以在 effect 内部创建 async 函数,并调用

核心代码:

// 错误演示:不要给 effect 添加 async
useEffect(async () => {
  const res = await axios.get('http://xxx')
  return () => {}
}, [])

// 正确使用
useEffect(() => {
  const loadData = async () => {
    const res = await axios.get('http://xxx')
  }
  loadData()
  
  return () => {}
}, [])

3.9 axios请求本地json数据

  • 需求:发起axios请求本地某json数据
  • 第一步:需要将json文件放在 public 目录下 !!!
  • 第二步:引入axios import axios from 'axios'
  • 第三步:发起请求
import React, { useEffect, useState } from 'react'
import axios from 'axios'
export default function App() {
  const [list, setList] = useState([])
  useEffect(() => {
//接口地址可省略 public    
axios.get('http://localhost:3000/data.json').then((res) => {
      console.log('打印res', res.data)
      setList(res.data.list)
    })
  }, [])
  return (
    <ul>
      {list.map((item) => (
        <li key={item.id}>{item.comment}</li>
      ))}
    </ul>
  )
}

到了这里,关于react之Hooks的介绍、useState与useEffect副作用的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • gitee版本回退本地和仓库的执行步骤(后悔药,无副作用,按说明书使用)

    目录 1.本地回退 1.打开项目文件夹 3.回退到指定版本 4.选择回退模式并确认 5.本地回退成功  2.回退仓库版本 1.在git上面找到项目的提交记录 2.找到提交错误的版本​编辑 3.双击新页面这个版本进去 点击操作再点击revert​编辑 4.确认回退  ​5.仓库回退成功 在使用后悔药之前

    2024年02月04日
    浏览(44)
  • C语言-程序环境和预处理(2)--带副作用的宏参数,宏与函数的对比,#undef,条件编译,文件包含

    上一篇文章–《C语言-程序环境和预处理(1)》讲述了程序的翻译环境和执行环境,编译、连接,预定义符号,#define,#符号和##符号的相关知识。 链接: 《C语言-程序环境和预处理(1)》 本篇文章,讲述带副作用的宏参数,宏与函数的对比,#undef,条件编译,文件包含的相

    2024年02月08日
    浏览(59)
  • react18中,useState 和 useEffect有什么区别

    useState 目的:useState用于在函数组件中添加状态。之前,只有类组件才能有自己的状态,但useState钩子使得函数组件也能够利用React的状态特性。 使用场景:当你需要在组件中存储、读取或更新一些数据时使用。例如,控制输入框的内容、切换按钮的状态等。 工作原理:useS

    2024年02月19日
    浏览(39)
  • react useState useEffect useMemo实际业务场景中的使用

    下面的代码实现了上面图片的功能

    2024年02月16日
    浏览(42)
  • React的hooks---useEffect

    在函数组件主体内(React 渲染阶段)改变 DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性 useEffect Hook 的使用则是用于完成此类副作用操作。 useEffect 接收一个包含命令式、且可能有副

    2024年02月15日
    浏览(36)
  • React Hooks 源码解析:useEffect

    React Hooks 源码解析(4):useEffect React 源码版本: v16.11.0 源码注释笔记:airingursb/react 1.1 为什么要有 useEffect 我们在前文中说到 React Hooks 使得 Functional Component 拥有 Class Component 的特性,其主要动机包括: 在组件之间复用状态逻辑很难 复杂组件变得难以理解 难以理解的 class 对

    2024年01月21日
    浏览(41)
  • React Hooks的useState、useRef使用

    React Hooks 是 React 16.8 版本引入的新特性,它允许你在不编写 class 的情况下使用 state 和其他 React 特性。其中, useState  和  useRef  是两个常用的 Hooks。 1. useState useState  是一个允许你在函数组件中添加 state 的 Hook。 使用说明: useState  返回一个状态变量和一个设置该变量的函

    2024年02月02日
    浏览(40)
  • React hooks之useEffect、useMemo优化技巧

    useEffect使用JSON.stringfy进行过滤,避免重复执行 将数组直接放入依赖数组可能不会按预期工作,因为数组比较是基于引用而不是内容。也就是说,如果数组引用没有变,即使数组内容发生了变化,副作用也不会重新运行。或者数组内饿哦那个没有改变但是引用却发生变化时,

    2024年02月12日
    浏览(46)
  • React hooks文档笔记(五)useEffect——解决异步操作竞争问题

    非bug,重新安装组件仅在开发过程中发生,帮助找到需要清理的效果。在生产环境中只会加载一次。 React 将在 Effect 下次运行之前以及卸载期间调用您的清理函数。 return () = {}; 在开发中, Effect call addEventListener() ,然后立即call removeEventListener() ,然后再次cal laddEventListener()

    2024年02月11日
    浏览(44)
  • React Hooks 详细使用介绍

    useState 是 React 中的一个基础 Hook,允许你在不使用 class 组件的情况下管理组件状态。 参数 初始值 你可以直接传递状态的初始值给 useState : 使用函数设置初始值 当初始化状态代价较大时,你可以传递一个函数: 返回值 useState 返回一个数组,其中包括当前状态值和一个更新

    2024年02月13日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包