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

React中Hooks--useEffect | useState | useCallback | useMemo

一、useEffect

useEffect 是 React 提供的一个 Hook,用于在函数组件中执行副作用操作(side effects),例如数据获取、订阅、或手动更改 DOM 等。useEffect 相当于类组件中的生命周期方法,但是它提供了更多的灵活性。

基本用法

useEffect 接受两个参数:

  1. Effect 函数:这是一个包含副作用操作的函数,它将在组件渲染到屏幕后执行。
  2. 依赖项数组:这个数组定义了 effect 函数依赖的组件状态或属性。如果数组中的值发生变化,effect 函数将重新执行。
示例:
import React, { useState, useEffect } from 'react';function Example() {const [count, setCount] = useState(0);// 基本的 useEffect:类似于 componentDidMount 和 componentDidUpdateuseEffect(() => {console.log('count is updated:', count);// 执行副作用操作...}, [count]); // 依赖项数组包含 count,当 count 变化时 effect 重新执行return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

清理副作用

useEffect 可以返回一个函数,这个函数在组件卸载或重新渲染前执行,用于清理副作用。

示例:
import React, { useState, useEffect } from 'react';function Example() {const [count, setCount] = useState(0);// 基本的 useEffect:类似于 componentDidMount 和 componentDidUpdateuseEffect(() => {console.log('count is updated:', count);// 执行副作用操作...}, [count]); // 依赖项数组包含 count,当 count 变化时 effect 重新执行return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

仅在组件挂载时执行

如果你希望副作用仅在组件挂载时执行一次,你可以传递一个空数组 [] 作为 useEffect 的第二个参数。

示例:
import React, { useState, useEffect } from 'react';function Example() {const [count, setCount] = useState(0);// 基本的 useEffect:类似于 componentDidMount 和 componentDidUpdateuseEffect(() => {console.log('count is updated:', count);// 执行副作用操作...}, [count]); // 依赖项数组包含 count,当 count 变化时 effect 重新执行return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

模拟 componentDidUpdate

如果你需要在组件更新时执行副作用,但不在挂载时执行,你可以使用非空的依赖项数组。

示例:
useEffect(() => {// 仅在特定 props 更新时执行console.log('特定 props 更新了');
}, [specificProp]); // 依赖项数组包含 specificProp

模拟 componentWillUnmount

如果你需要在组件卸载时执行清理操作,可以返回一个函数。

示例:
useEffect(() => {function handleStorageChange() {// 处理存储变化}window.addEventListener('storage', handleStorageChange);// 组件卸载时的清理操作return () => {window.removeEventListener('storage', handleStorageChange);};
}, []); // 空依赖项数组,仅在组件挂载时执行一次

总结

useEffect 提供了一种灵活的方式来处理组件的副作用操作,它使得函数组件能够执行原本需要在类组件的生命周期方法中执行的操作。通过依赖项数组,useEffect 能够智能地决定何时执行副作用函数,从而避免不必要的副作用执行和潜在的性能问题。

二、useState

useState 是 React 的一个 Hook,它允许你在函数组件中添加 React 状态。这个 Hook 是 React 16.8+ 版本引入的,并且成为了在函数组件中处理状态的首选方式。

基本用法

useState 接受一个参数:初始状态(可以是任何类型,包括对象、数组、基本类型等)。它返回一个数组,包含两个元素:

  1. 当前状态:组件的状态值。
  2. 更新状态的函数:允许你更新状态,这个函数调用时可以传入一个新的状态值,React 将负责重新渲染组件。
示例:
import React, { useState } from 'react';function Counter() {// 初始化状态为 0const [count, setCount] = useState(0);return (<div><p>Count: {count}</p><button onClick={() => setCount(count + 1)}>Increment</button><button onClick={() => setCount(count - 1)}>Decrement</button></div>);
}

在这个例子中,count 是当前的状态值,setCount 是更新这个状态的函数。

使用函数更新状态

你可以在调用更新函数时传递一个函数,这个函数接收上一个状态作为参数,并返回新的状态。这在你需要基于前一个状态来计算新状态时非常有用。

示例:
function Counter() {const [count, setCount] = useState(0);const incrementCount = () => {setCount((prevCount) => prevCount + 1);};return (<div><p>Count: {count}</p><button onClick={incrementCount}>Increment</button></div>);
}

多个状态变量

如果你需要在组件中使用多个状态变量,你可以调用 useState 多次来分别创建它们。

示例:
function Form() {const [username, setUsername] = useState('');const [password, setPassword] = useState('');// 其他逻辑...return (<form><inputtype="text"value={username}onChange={(e) => setUsername(e.target.value)}/><inputtype="password"value={password}onChange={(e) => setPassword(e.target.value)}/>{/* 其他表单元素 */}</form>);
}

总结

useState 是函数组件中处理状态的核心 Hook,它使得在函数组件中使用状态变得简单直接。通过 useState,你可以轻松地添加、更新和维护组件的状态,同时享受 React 的响应式更新和性能优化。

三、useCallback

useCallback 是 React 提供的一个 Hook,它用于记忆化(memoization)函数。这意味着 React 会返回同一个函数引用,只要依赖项数组中的值没有变化。这在性能优化中非常有用,特别是当你希望避免在每次渲染时创建新的函数实例,或者在子组件中使用这些函数时。

基本用法

import React, { useCallback } from 'react';function MyComponent() {// 定义一个函数const myFunction = (arg) => {console.log(arg);};// 使用 useCallback 记忆化该函数const memoizedFunction = useCallback(myFunction, []); // 空依赖数组// memoizedFunction 现在是一个记忆化的函数// 只要组件没有重新渲染,它就会保持相同的引用return <div onClick={() => memoizedFunction('Hello!')}>Click me!</div>;
}

useCallback 是 React 提供的一个 Hook,它用于记忆化(memoization)函数。这意味着 React 会返回同一个函数引用,只要依赖项数组中的值没有变化。这在性能优化中非常有用,特别是当你希望避免在每次渲染时创建新的函数实例,或者在子组件中使用这些函数时。

基本用法

 

import React, { useCallback } from 'react'; function MyComponent() { // 定义一个函数 const myFunction = (arg) => { console.log(arg); }; // 使用 useCallback 记忆化该函数 const memoizedFunction = useCallback(myFunction, []); // 空依赖数组 // memoizedFunction 现在是一个记忆化的函数 // 只要组件没有重新渲染,它就会保持相同的引用 return <div onClick={() => memoizedFunction('Hello!')}>Click me!</div>; }

参数说明

  • 第一个参数:要记忆化的函数。
  • 第二个参数:依赖项数组。只有当这个数组中的值发生变化时,React 才会重新创建函数。

使用场景

  1. 避免子组件的不必要渲染: 当你将回调函数传递给子组件,并且子组件在渲染时使用了这个函数,如果父组件每次渲染都创建一个新的函数实例,子组件可能会因为引用变化而重新渲染。

  2. 优化性能: 通过记忆化,可以减少不必要的计算和 DOM 操作,提高应用性能。

  3. useMemo 结合使用: 有时候,你不仅需要记忆化函数,还需要记忆化计算结果。useCallback 可以与 useMemo 一起使用来优化性能。

  4. 在事件处理器中使用: 事件处理器函数经常作为属性传递给 DOM 元素,使用 useCallback 可以避免因函数引用变化导致的重复渲染。

  5. useEffect 或其他 Hook 中使用: 当回调函数用于 useEffect 或其他 Hook 时,使用 useCallback 可以确保这些 Hook 在不必要的情况下不会运行。

注意事项

  • 当使用 useCallback 时,确保依赖项数组包含了所有外部依赖,以避免记忆化失败。
  • 如果依赖项数组为空([]),那么回调函数只会在组件挂载时创建一次。
  • 记忆化的函数不应该有任何副作用,因为它们可能会在组件的整个生命周期内保持不变。

通过使用 useCallback,你可以更好地控制 React 组件的性能和渲染行为。

四、useMemo

useMemo 用于记忆化复杂计算的结果,确保只有在依赖项变化时才重新计算,从而避免不必要的性能开销。

基本用法:

const memoizedValue = useMemo(() => {// 这里是你的计算逻辑return someExpensiveComputation(a, b);
}, [a, b]); // 依赖项数组
  • 第一个参数:一个函数,它返回你想要记忆化的值。这个函数只有在依赖项变化时才会执行。
  • 第二个参数:依赖项数组。只有当这个数组中的某个元素发生变化时,函数才会重新执行,并且返回的新值会替换缓存的值。

特点

  • useMemo 仅在其依赖项变化时才重新计算。如果依赖项没有变化,它将返回缓存的值,而不是重新执行函数。
  • 它非常适合用于性能优化,尤其是在处理复杂的计算或大数据集时。

使用场景

  1. 避免重复的计算:当某个计算结果在多次渲染中保持不变时,使用 useMemo 可以避免不必要的计算。

  2. 优化渲染性能:通过缓存结果,减少渲染期间的计算量,提高渲染性能。

  3. 与依赖项解耦:当计算结果与组件的多个属性或状态相关联时,useMemo 可以确保只在相关依赖项变化时重新计算。

示例

假设你有一个组件,它根据传入的数值进行一些复杂的计算:

import React, { useMemo } from 'react';function MyComponent({ a, b }) {// 使用 useMemo 来记忆化计算结果const result = useMemo(() => {// 假设这是一个昂贵的计算const expensiveComputation = (x, y) => {// ...进行一些计算...return x * y;};return expensiveComputation(a, b);}, [a, b]); // 当 a 或 b 变化时,重新计算return (<div><p>The result is: {result}</p></div>);
}

在这个示例中,result 只有在 ab 发生变化时才会重新计算。如果没有变化,它将返回缓存的值,从而避免重复的计算。

注意事项

  • 确保依赖项数组完整,否则可能会导致错误的缓存结果。
  • 不要将 useMemo 用于包含副作用的计算,它只适用于纯计算。
  • 使用 useMemo 可以提高性能,但也要小心不要过度使用,因为它可能会增加内存使用。

通过合理使用 useMemo,你可以有效地优化 React 组件的性能,减少不必要的计算和渲染。

useCallback 和 useMemo的区别:

  1. 记忆化内容

    • useCallback 记忆化函数。
    • useMemo 记忆化计算结果。
  2. 返回值

    • useCallback 返回一个函数。
    • useMemo 返回计算结果。
  3. 使用时机

    • useCallback 通常用于事件处理器或传递给子组件的函数。
    • useMemo 通常用于优化性能,避免在渲染期间进行昂贵的计算。
  4. 副作用

    • useCallback 的函数不应该包含副作用。
    • useMemo 的函数可以执行计算,但不应该包含副作用。
  5. 依赖项变化时的行为

    • 当依赖项变化时,useCallback 会重新创建函数。
    • 当依赖项变化时,useMemo 会重新执行计算函数。

示例

import React, { useMemo, useCallback } from 'react';function MyComponent(a, b) {// 记忆化回调函数,避免子组件不必要渲染const handleClick = useCallback(() => {console.log('Clicked with', a, b);}, [a, b]);// 记忆化计算结果,避免重复计算const computedValue = useMemo(() => {return a * b;}, [a, b]);return (<div><button onClick={handleClick}>Click me</button><p>Computed Value: {computedValue}</p></div>);
}

一边学习一边更新~~

相关文章:

  • 架构师工作报告
  • 一篇讲清楚怎么选算力租赁平台!
  • 什么情况下需要使用接地电阻柜
  • AI + 3D:用单个图像和文本提示创建可交互的3D世界
  • 产品经理经验分享:电商类项目开发需要了解常用的电商API接口
  • 记录一下 Chrome浏览器打印时崩溃问题
  • ifconfig eth0 hw ether
  • 单链表的创建及排序
  • 【Python】Redis数据库
  • SQL优化选对执行计划,查询速度提升1000倍 | OceanBase 应用实践
  • 长期保存红酒的挑战与应对策略
  • 【TensorFlow深度学习】使用TensorFlow实现双DQN与优先级经验回放
  • Git 代码管理规范 !
  • 9.4JavaEE——声明式事务管理(一)基于XML方式的声明式事务
  • 【Linux】Jenkins Pipeline流水线详解及基于Jenkins流水线实现自动更新项目(实战)
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • Django 博客开发教程 16 - 统计文章阅读量
  • Docker下部署自己的LNMP工作环境
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Java|序列化异常StreamCorruptedException的解决方法
  • java8 Stream Pipelines 浅析
  • JavaScript 奇技淫巧
  • Laravel 实践之路: 数据库迁移与数据填充
  • MySQL的数据类型
  • Python - 闭包Closure
  • Web设计流程优化:网页效果图设计新思路
  • yii2中session跨域名的问题
  • 构建工具 - 收藏集 - 掘金
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 面试遇到的一些题
  • 前端面试之闭包
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 用Visual Studio开发以太坊智能合约
  • 智能合约Solidity教程-事件和日志(一)
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • (¥1011)-(一千零一拾一元整)输出
  • (LeetCode C++)盛最多水的容器
  • (Note)C++中的继承方式
  • (含笔试题)深度解析数据在内存中的存储
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (转)linux 命令大全
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .mysql secret在哪_MYSQL基本操作(上)
  • .Net Core 中间件与过滤器
  • .Net Core中Quartz的使用方法
  • .net 桌面开发 运行一阵子就自动关闭_聊城旋转门家用价格大约是多少,全自动旋转门,期待合作...
  • .net程序集学习心得
  • .NET精简框架的“无法找到资源程序集”异常释疑
  • ?.的用法
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • [Android] Upload package to device fails #2720