React + 项目(从基础到实战) -- 第三期

react内置hooks

useState

如何让页面动起来(实时更新)

import React,{FC,useState} from "react";

  

const Demo:FC=()=>{

   let count=0; //普通js变量无法触发组件更新

  

  

   function add(){

    count++;

   
    console.log("count: ",count);

   }

    return <div>

        <button onClick={add}>add {count}</button>

    </div>

}

  
  

export default Demo;

在这里插入图片描述

为什么采用

state的改变可以触发函数组件的更新
(如果js变量不在jsx中使用,别用useState)

import React,{FC,useState} from "react";

  

const Demo:FC=()=>{

//    let count=0; //普通js变量无法触发组件更新

   const[count,setCount]=useState(0); //useState 可以触发组件更新

  

   function add(){

    // count++;

    setCount(count+1)

    console.log("count: ",count);

   }

    return <div>

        <button onClick={add}>add {count}</button>

    </div>

}

  
  

export default Demo;

在这里插入图片描述

特点

  1. 不可变数据
    不修改原数据,而是传入新的值

  2. 异步更新|
    函数中无法直接获取最新的值
    在这里插入图片描述

  3. 可能被合并
    使用函数state可以解决这个问题

在这里插入图片描述

 setCount(()=>{

        return count+5

    })

immer

是一个插件
解决state不可变数据的影响
安装 npm install -D immer

 import {FC,useState} from "react";

import {produce} from "immer";

  

const Demo : FC =()=>{

  

    const [list,setList]=useState(['x','y'])

    function add(){

        // setList(list.concat('z'));

        setList(

            produce(draft=>{

                draft.push('z')//直接在原数组上修改

            })

        )

  

    }

  

    return (

        <div>

        <h2>state 不可变数据</h2>

        <div>{JSON.stringify(list)}</div>

        <button onClick={add}>add  item</button>

  
  

        </div>

    )

}

  

export default  Demo;

useEffect

为什么

组件是一个函数,返回的是JSX片段,
组件初次渲染完成,即函数执行完成,
一般情况下函数执行完成就结束了
但是在state更新时,会触发组件更新,函数组件再次执行

为了解决以上问题,使用useEffect

import {FC,useEffect,useState} from "react"

const Demo:FC=()=>{

    useEffect(()=>{

        console.log("组件初次渲染完成");

  

        return ()=>{

            console.log("组件销毁时执行");

        }

    },[])//无依赖项,只执行一次

  

    const[count,setCount]=useState(0); //useState 可以触发组件更新

  

   function add(){

    // count++;

    setCount(()=>{

        return count+5

    })

    console.log("count: ",count);

   }

    return <div>

        <button onClick={add}>add {count}</button>

    </div>

  

}

  
  

export default Demo;

注意

发现useEffect 执行两次

在react 18 中,useEffect 在开发环境中执行两次,在生产环境中执行一次
(模拟组件生命周期,以便尽早暴露问题)
开发环境 npm run build 生存环境

useRef

  1. 操作DOM
  2. 可传入普通js变量,但是更新不会触发rerender

与vue3 ref 不同

  

import { FC,useRef } from "react";

  

const Demo:FC = () => {

     // 定义一个ref

    const inputRef = useRef<HTMLInputElement>(null) //dom节点

    const nameRef=useRef("pink") //不是dom节点,是一个普通的js变量

    function selectInput(){

        const input = inputRef.current;

        if(input){

            input.select(); // 选中输入框中的内容(Dom节点操作API)

        }

    }

  

    function changeName(){

        nameRef.current="blue"//修改ref的值,不引起rerender(state修改会触发组件更新)

        console.log(nameRef.current);

    }

    return (

        <>

        <input ref={inputRef} defaultValue={"hello world"}/>

        <button onClick={selectInput}>选中 input</button>

  

        <p>{nameRef.current}</p>

        <button onClick={changeName}>修改名字</button>

  

        </>

    )

}

  
  

export default Demo;

在这里插入图片描述

useMemo

缓存数据
不用每次执行函数组件(比如说 state修改)都重新生成 , 实现性能优化

import {FC,useMemo,useState} from "react"

  

const Demo : FC =()=>{

    const[num1,setNum1]=useState(0)

    const[num2,setNum2]=useState(0)

    const[text,setText]=useState("hello") //更新导致组件rerender

  
  

    const sum =useMemo(()=>{

        console.log("计算两数之和");//缓存

        return num1+num2;

    },[num1,num2])

  

    return (

        <>

        <p>sum = {sum}</p>

        <button onClick={()=>{setNum1(num1+1)}}>num1 : {num1}</button>

        <button onClick={()=>{setNum2(num2+1)}}>num2 : {num2}</button>

        <button onClick={()=>{setText(text+"1")}}>text : {text}</button>

        </>

    )

}

  
  
  

export default Demo;

在这里插入图片描述

useCallback

缓存函数

import {FC,useCallback,useState} from "react"

  
  

const Demo : FC =()=>{

    const [text,setText] = useState("hello")

    const fn1=()=>{

        console.log("fn1 text",text);

    }

  

    const fn2=useCallback(()=>{

        console.log("fn2 text",text);

    },[text])

  

    return(

        <>

        <button onClick={fn1}>fn1</button>

        <button onClick={fn2}>fn2</button>

        <div>

            <input value={text} onChange={e=>setText(e.target.value)}></input>

        </div>

        </>

    )

}

  
  
  

export default Demo;

自定义hooks

抽离公共部分,复用代码

同步案例

监听鼠标位置

  1. 自定义hook
import { useState,useEffect } from "react";

  

//获取鼠标位置

function useMouse(){

    const [x,setX]=useState(0);

    const [y,setY]=useState(0);

    const mouseMoveHandler=(e:MouseEvent)=>{

        setX(e.clientX);

        setY(e.clientY);

    }

  
  

    useEffect(()=>{

    //监听鼠标事件

        window.addEventListener('mousemove',mouseMoveHandler);

    //组件销毁时,一定要解绑DOM事件!!(可能会导致内存泄漏问题)

    return ()=>{

        window.removeEventListener('mousemove',mouseMoveHandler);

    }

    },[])

  
  

    return {x,y}

  

}

  
  

export default useMouse;
  1. app.tsx 中引入
//导入自定义hook


import useMouse from "./hooks/useMouse.ts";

function App() {


  const {x, y} = useMouse();

  return(

    <>

    <p>

      App Page

    </p>

    <div>x: {x}</div>

    <div>y: {y}</div>
    </>

  )

  

}

  

export default App

异步案例

模拟加载效果

import { useState,useEffect } from "react";

//异步获取消息

function getInfo():Promise<string>{

    return new Promise(resolve=>{

        setTimeout(()=>{

          resolve(Date.now().toString())  

        },1500)

    })

}

  
  

//自定义钩子

const useGetInfo=()=>{

    const[loading,setLoading]=useState(true)

    const[info,setInfo]=useState("")

  

    useEffect(()=>{

        getInfo().then(info=>{

            setLoading(false)

            setInfo(info)

        })

    },[])

    return {loading,info}

}

  
  

export default useGetInfo;

第三方hooks

提高开发效率

ahooks

react-hooks

hooks使用规则

  1. useXxx命名
  2. 组件内 获 其他hook 中可以调用
  3. 保证每次调用顺序一致(不能处于 if/for 内部)

面试题(闭包陷阱)

无法获取最新值

import {FC,useState} from 'react'

  

const Demo:FC =()=>{

    const[count,setCount]=useState(0)

    function add(){

        setCount(count+1)

    }

  

    function alertFn(){

      setTimeout(()=>{

        alert(count);

      },3000)

    }

  

    return(

        <>

        <p>闭包陷阱</p>

  

        <div>

        <span>{count}</span>

        <button onClick={add}>add</button>

        <button onClick={alertFn}>alert</button>

  

        </div>

        </>

    )

}

  
  

export default Demo;

使用ref解决在这里插入图片描述

import {FC,useState,useRef, useEffect} from 'react'

  

const Demo:FC =()=>{

    const[count,setCount]=useState(0)

    const countRef = useRef(0)

  

    function add(){

        setCount(count+1)

    }

  

    useEffect(()=>{

        countRef.current=count

    },[count])

  

    function alertFn(){

      setTimeout(()=>{

        // alert(count); //count 值类型

        alert(countRef.current); // ref 引用类型

      },3000)

    }

  

    return(

        <>

        <p>闭包陷阱</p>

  

        <div>

        <span>{count}</span>

        <button onClick={add}>add</button>

        <button onClick={alertFn}>alert</button>

  

        </div>

        </>

    )

}

  
  

export default Demo;

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(免费分享)基于微信小程序自助停取车收费系统

本项目的开发和制作主要采用Java语言编写&#xff0c;SpringBoot作为项目的后端开发框架&#xff0c;vue作为前端的快速开发框架&#xff0c;主要基于ES5的语法&#xff0c;客户端采用微信小程序作为开发。Mysql8.0作为数据库的持久化存储。 获取完整源码&#xff1a; 大家点赞…

基于SpringBoot的“简历系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“简历系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 管理员登录界面图 用户管理界面图 简历模板管理界面图…

Ubuntu Desktop 安装有道词典

Ubuntu Desktop 安装有道词典 1. 有道词典2. Installation2.1. 解压 deb 包到 youdao 目录2.2. 解压 deb 包中的 control 信息 (包的依赖写在该文件里面)2.3. 编辑 control 文件&#xff0c;删除依赖里面的 gstreamer0.10-plugins-ugly2.4. 创建 youdaobuild 目录&#xff0c;重…

数据结构—红黑树

红黑树介绍 红黑树&#xff08;Red Black Tree&#xff09;是一种自平衡二叉查找树。由于其自平衡的特性&#xff0c;保证了最坏情形下在 O(logn) 时间复杂度内完成查找、增加、删除等操作&#xff0c;性能表现稳定。 在 JDK 中&#xff0c;TreeMap、TreeSet 以及 JDK1.8 的 …

2024-04-03 NO.4 Quest3 手势追踪抓取物体

文章目录 1 手势抓取方式1.1 Hand Grab1.2 Touch Hand Grab1.3 Distance Hand Grab 2 HandGrabExamples 示例场景2.1 Interactor 对象2.2 Interactable 对象2.2.1 父子结构2.2.2 “Hand Grab lnteractable” 脚本2.2.3 “Move Towards Target Provider” 脚本2.2.4 其他 Moveme…

C#编写MQTT客户端软件

主要参考C#MQTT编程06--MQTT服务器和客户端(winform版)_c#mqttserver-CSDN博客 但由于使用的.NET版本和MQTT库版本存在差异&#xff0c;因此有些不同。 MQTT协议内容在此不做描述&#xff0c;仅介绍VS使用C#的实现过程。本次使用VS2015&#xff0c;.netframwork4.6。 C#语言本身…

LeetCode每日一题之专题一:双指针 ——复写零

复写零OJ链接&#xff1a;1089. 复写零 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 解法&#xff08;原地复写-双指针&#xff09;&#xff1a; 算法思路&#xff1a; 如果「从前向后」进⾏原地复写操作的话&#xff0c;由于 0 的出现会复写两次&#xff0c;导致…

无法打开pycharm虚拟环境

问题&#xff1a;在pycharm的terminal中执行pip命令&#xff0c;但是下载的包没有安装到该项目的虚拟环境中。 激活虚拟环境&#xff0c;打开terminal&#xff0c;执行myenv\Scripts\activate&#xff0c;显示执行出错 无法加载文件 D:\Project\RF_Project\venv\Scripts\acti…

1999-2022年各省研究与试验发展经费内部支出数据/研发经费内部支出数据/RD经费内部支出数据

1999-2022年各省研究与试验发展经费内部支出数据/研发经费内部支出数据/R&D经费内部支出数据 1、时间&#xff1a;1999-2022年 2、来源&#xff1a;整理自科技年鉴 3、指标&#xff1a;研究与试验发展经费内部支出/R&D经费内部支出/研发经费内部支出 4、范围&#…

Stable Diffusion 本地化部署

一、前言 最近在家背八股文背诵得快吐了&#xff0c;烦闷的时候&#xff0c;看到使用 AI 进行作图&#xff0c;可以使用本地话部署。刚好自己家里的电脑&#xff0c;之前买来玩暗黑4&#xff0c;配置相对来说来可以&#xff0c;就拿来试试。 此篇是按照 Github 上的 stable-d…

Leetcode 1143. 最长公共子序列

心路历程&#xff1a; 这道题还是按照之前公共子数组的角度去思考的话会超时&#xff0c;即考虑最后一个元素一定是公共子序列的最后一个元素。需要换一种建模思路&#xff0c;从而简化整个递推过程。 状态&#xff1a;以i, j为结尾的区间的最长公共子序列&#xff0c;text1[…

【HTML】简单制作一个动态3D正方体

目录 前言 开始 HTML部分 JS部分 CSS部分 效果图 总结 前言 无需多言&#xff0c;本文将详细介绍一段代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建两个文本文档&#xff0c;其中HTML的文件名改为[index.html]&#xff0c;JS的文件名改…

智慧展览馆:基于AI智能识别技术的视频智慧监管解决方案

一、建设背景 随着科技的不断进步和社会安全需求的日益增长&#xff0c;展览馆作为展示文化、艺术和科技成果的重要场所&#xff0c;其安全监控系统的智能化升级已成为当务之急。为此&#xff0c;旭帆科技&#xff08;TSINGSEE青犀&#xff09;基于视频智能分析技术推出了展览馆…

Windows下Docker安装Kafka3+集群

编写 docker-compose.yaml 主要参照&#xff1a;https://www.cnblogs.com/wangguishe/p/17563274.html version: "3"services:kafka1:image: bitnami/kafka:3.4.1container_name: kafka1environment:- KAFKA_HEAP_OPTS-Xmx1024m -Xms1024m- KAFKA_ENABLE_KRAFTyes- K…

在s390x架构机器上构建frps/frpc镜像 —— 筑梦之路

源码&#xff1a;GitHub - fatedier/frp: A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet. # 克隆代码git clone https://github.com/fatedier/frp.git# 切换目录cd frp# 构建frps服务端docker build -t frps:s390x -f …

04 Python进阶:MySQL-PyMySQL

什么是 PyMySQL&#xff1f; PyMySQL 是一个用于 Python 的纯 Python MySQL 客户端库&#xff0c;提供了与 MySQL 数据库进行交互的功能。PyMySQL 允许 Python 开发人员连接到 MySQL 数据库服务器&#xff0c;并执行诸如查询、插入、更新和删除等数据库操作。 以下是 PyMySQL …

MySQL查询数据大小

在 MySQL 数据库中&#xff0c;有一个内置的库叫做 information_schema&#xff0c;该数据库中的 tables 表包含了数据库中所有表的基本信息&#xff0c;tables 表结构如下&#xff1a; 下面介绍几个主要关键字段&#xff1a; TABL_SCHEMA&#xff1a;表所属的数据库名TABLE_N…

使用deepspeed,transformers,safetensor中常见的训练精度,共享权重问题

使用deepspeed可能需要注意精度问题 混合精度&#xff0c;LayerNorm 虽然deepspeed有混合精度训练的功能&#xff0c;但是对于网络上各种奇奇怪怪的代码的DIY转化中&#xff0c;他还是很弱小的。它的精度问题&#xff0c;使用deepspeed如果模型中有部分模型使用的是half精度&a…

0基础如何进入IT行业?

前言 俗话说得好“隔行如隔山”&#xff0c;每个人从事自己陌生的行业都是十分艰难的。但现在网上不是流行一种这样的说法吗&#xff1f;360行&#xff0c;行行转IT。我觉得这个说的真的挺对的&#xff0c;因为从我身边认识的同事确实有很多大学并非是计算机科学专业的&#x…

【项目新功能开发篇】开发编码

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…