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

news2024/11/20 16:34:03

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;

在这里插入图片描述

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

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

相关文章

Transformer模型-用jupyter演示逐步计算attention

学习transformer模型-用jupyter演示如何计算attention&#xff0c;不含multi-head attention&#xff0c;但包括权重矩阵W。 input embedding&#xff1a;文本嵌入 每个字符用长度为5的向量表示&#xff1a; 注意力公式&#xff1a; 1&#xff0c;准备Q K V&#xff1a; 先 生…

云计算的安全需求

目录 一、概述 二、云安全服务基本能力要求 三、信息安全服务&#xff08;云计算安全类&#xff09;资质要求 3.1 概述 3.2 资质要求内容 3.2.1 组织与管理要求 3.2.2 技术能力要求 四、云安全主要合规要求 4.1 安全管理机构部门的建立 4.2 安全管理规范计划的编制 4…

AR/VR技术对制造业劳动力危机的影响

借助 AR/VR 的力量缩小现代制造业的技能差距 数字化转型仍然是企业的首要任务&#xff0c;其许多方面都需要人工干预。然而&#xff0c;推动此类举措所需的技术工人日益短缺。这就造成了我们所说的“制造业劳动力危机”。 制造业应当如何&#xff1a; 制造业用工危机正在影响…

IDEA 中能提高开发效率的插件

目录 前言 插件 Rainbow Brackets AceJump POJO to JSON Json Helper MybatisX Maven Helper PlantUML Integration TONYYI Lingma 前言 IDEA 里又很多好用的插件可以帮助我们提升开发效率&#xff0c;这里罗列下自己开发过程中常用的插件&#xff0c;善于利用插件&…

MySQL-视图:视图概述、创建、查看、更新、修改、删除

第14章 视图 1. 常见的数据库对象2. 视图概述2.1 为什么使用视图&#xff1f;2.2 视图的理解 3. 创建视图3.1 创建单表视图3.2 创建多表联合视图3.3 基于视图创建视图 4. 查看视图5. 更新视图的数据5.1 一般情况5.2 不可更新的视图 6. 修改、删除视图6.1 修改视图6.2 删除视图 …

Prisma ORM 5.12 发布,支持 Cloudflare D1 数据库

昨晚&#xff0c;Prisma ORM 发布了 5.12.0 稳定版本&#xff0c;在此版本中 Prisma ORM 新增了对 Cloudflare D1 的预览支持&#xff0c;现在我们可以选择将本地的 SQLite 数据库逐步迁移到 Cloudflare 上面&#xff0c;从而实现无需额外成本即可构建处理大量用户的应用程序。…

[计算机效率] 格式转换工具:格式工厂

3.14 格式转换工具&#xff1a;格式工厂 格式工厂是一款功能强大的多媒体格式转换软件&#xff0c;可以实现音频、视频、图片等多种格式的转换。它支持几乎所有类型的多媒体格式&#xff0c;包括视频、音频、图片、字幕等&#xff0c;可以轻松实现格式之间的转换&#xff0c;并…

MySQL 索引底层探索:为什么是B+树?

MySQL 索引底层探索&#xff1a;为什么是B树&#xff1f; 1. 由一个例子总结索引的特点2. 基于哈希表实现的哈希索引3. 高效的查找方式&#xff1a;二分查找4. 基于二分查找思想的二叉查找树5. 升级版的BST树&#xff1a;AVL 树6. 更加符合磁盘特征的B树7. 不断优化的B树&#…

类似微信的以文搜图功能实现

通过PaddleOCR识别图片中的文字&#xff0c;将识别结果报存到es中&#xff0c;利用es查询语句返回结果图片。 技术逻辑 PaddleOCR部署、es部署创建mapping将PaddleOCR识别结果保存至es通过查询&#xff0c;返回结果 前期准备 PaddleOCR、es部署请参考https://blog.csdn.net…

安装Qrcode库的方法最终解答!_Python第三方库

安装Python第三方库Qrcode 我的环境&#xff1a;Window10&#xff0c;Python3.7&#xff0c;Anaconda3&#xff0c;Pycharm2023.1.3 Qrcode库 Qrcode库是一个专门生成二维码的库。它能够让你很容易地创建不同大小、颜色和包含不同类型数据的二维码&#xff0c;支持生成 GIF 动…

基于springboot实现影城管理系统项目【项目源码+论文说明】

基于springboot实现影城管理系统演示 摘要 随着现在网络的快速发展&#xff0c;网上管理系统也逐渐快速发展起来&#xff0c;网上管理模式很快融入到了许多生活之中&#xff0c;随之就产生了“小徐影城管理系统”&#xff0c;这样就让小徐影城管理系统更加方便简单。 对于本小…

前端(动态雪景背景+动态蝴蝶)

1.CSS样式 <style>html, body, a, div, span, table, tr, td, strong, ul, ol, li, h1, h2, h3, p, input {font-weight: inherit;font-size: inherit;list-style: none;border-spacing: 0;border: 0;border-collapse: collapse;text-decoration: none;padding: 0;margi…

Spring Cloud微服务入门(二)

微服务的技术栈 服务治理&#xff1a; 服务注册、发现、调用。 负载均衡&#xff1a; 高可用、集群部署。 容错&#xff1a; 避免雪崩、削峰、服务降级。 消息总线&#xff1a; 消息队列、异步通信&#xff0c;数据一致性。 网关&#xff1a; 校验路径、请求转发、服务集成…

AlgorithmStar(AS机器学习与科学计算库) 实现 矩阵数据类型的计算函数汇总

AlgorithmStar 实现 矩阵 计算 AlgorithmStar 本文中将会演示通过 AS 机器学习库 实现 矩阵计算 目录 文章目录 AlgorithmStar 实现 矩阵 计算目录矩阵创建通过数组创建通过稀疏矩阵创建通过填充创建矩阵通过随机的方式创建矩阵 矩阵计算矩阵的基本运算矩阵的加法计算矩阵的减…

Cloud flare反向代理流量实验

前言 本实验将会为大家解析cloud flare的反向解析代理服务如何搭建&#xff0c;works如何创建等等。本文中教学创建的实例已在文章编写结束后释放&#xff0c;该项技术不可用于违法用途&#xff01;违者自行承担后果&#xff01;&#xff01; 原理拓扑图 一、知识链条 1、Clou…

JavaScript(六)---【回调、异步、promise、Async】

零.前言 JavaScript(一)---【js的两种导入方式、全局作用域、函数作用域、块作用域】-CSDN博客 JavaScript(二)---【js数组、js对象、this指针】-CSDN博客 JavaScript(三)---【this指针&#xff0c;函数定义、Call、Apply、函数绑定、闭包】-CSDN博客 JavaScript(四)---【执…

STM32的I2C补充说明

1.前言 前面不是开发了F407的i2c嘛&#xff0c;最近做项目有三四个i2c器件&#xff0c;项目要求用f103&#xff0c;于是看了一下f103&#xff0c;发现并没有多大区别&#xff0c;下面我会说一下异同。还有关于接收的过程也有要补充的。 2.F103 VS F407 两者之间几乎没有区别&a…

Maven 项目之快速选择环境配置文件

Maven项目中&#xff0c;多环境之间如何进行配置文件的切换。在我们开发的过程中&#xff0c;经常会出现开发环境、测试环境、生产环境等之间的切换&#xff0c;如果我们每次都去替换配置文件&#xff0c;就会跟繁琐&#xff0c;这个时候就可以创建多个环境&#xff0c;同时在对…

下载页面上的视频

引言&#xff1a;有些页面上的视频可以直接右键另存为或者F12检索元素找到视频地址打开后保存&#xff0c;但有些视频页面是转码后的视频&#xff0c;不能直接另存为视频格式&#xff0c;可以参考下本方法 以该页面视频为例&#xff1a;加载中...点击查看详情https://wx.vzan.c…

zookeeper监听集群节点的实现zkclient组件实现方案(Java版)

ZooKeeper Watcher 机制 client 向zookeeper 注册监听client注册的同时会存储一个WatchManager对象向zookeeper发生改变则notification client 并发送一个WatchManager对象,然后client再更新该对象 package com.jacky.zk.demo;import org.I0Itec.zkclient.IZkChildListener;…