首页 > 其他分享 >React函数组件Hook

React函数组件Hook

时间:2024-03-21 11:00:00浏览次数:31  
标签:count react 函数 React Hook 组件 import

问题: 相对于类组件, 函数组件的编码更简单, 效率也更高, 但函数组件不能有state (旧版)

解决: React 16.8版本设计了一套新的语法来让函数组件也可以有state

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

  • Hook也叫钩子,本质就是函数,能让你使用 React 组件的状态和生命周期函数...

  • Hook 语法 基本已经代替了类组件的语法

  • 后面的 React 项目就完全是用Hook语法了

Hook API 索引 – React 官方文档: Hook API 索引 – React

hook函数和普通函数的区别:

hook函数本身就是一个函数。react通过函数名来判断是普通函数还是hook函 数,以useXxx 格式命名的就是hook函数。

Hook函数使用原则:

1.不能在类组件中使用,不能在普通函数中使用

2.只能在函数组件中使用,或其他hook函数中使用【react提供的,第三方的,自定义的】

3..hook函数必须是数量确定的,不能写在逻辑判断中或后,不能写在循环中

4.应用时,一般写在顶级作用域的首行 使用场景

-----1.可以在函数组件中使用

let [msg, setMsg] = useState('')
 function clickHandler(){
 // let [count,setCount] = useState() // 普通函数会报错

 }

-----2.自定hook中可以使用其他hook

function useClickHandler(){
 let [count,setCount] = useState(0)
 }

-----3.如果函数名首字母大写,他会 认为是函数组件,也不会报错

 function ClickHandler(){
 let [count,setCount] = useState(0)
 }

1.useState()

作用:给函数组件添加状态

返回值:是一个数组,第一个元素是状态,第二个元素是设置状态的函数

语法:let [状态, 设置状态函数] = useState(初始值)

import React,{useState} from 'react'

export default function App() {
    console.log('App render')
   let [count,setCount] = useState(0)
    return (
        <div>
            <h3>App</h3>
            <p>{count}</p>
            <p><button onClick={()=>{
             setCount(1000)
            }}>count + 1</button></p>
        </div>
    )
}

2.useEffect

作用:用来模拟函数组件的生命周期 componentDidMount、componentDidUpdate、ComponentWillUnmounted

2.1.用法:

useEffect(回调函数) : 没有第二个参数 模拟 componentDidMount + componentDidUpdate

useEffect(() => {
 console.log('useEffect') 
})
2.2.用法

useEffect(回调函数,[]) 只模拟 componentDidMount

 useEffect(()=>{
        console.log('useEffect')   // componentDidMount
 },[])
2.3.用法

useEffect(回调函数,[某 个自身状态(state) , 某个 外部状态(props), .......])

useEffect(() => { 
 console.log('useEffect')
 }, [count])
2.4.用法

useEffect( return ()=>{ } )   模拟componentWillUnmount

useEffect(()=>{
 console.log('Test useEffect')
 return ()=>{ // componentWillUnmount
 console.log('destroy')
 }
 },[msg,money])

3.useRef

作用 :可以用它获取dom元素

1. 创建一个ref let divRef = useRef()

2. 绑定ref

3. 获取dom元素

import React, { useRef } from "react";
export default function App() {
  let divRef = useRef();
  return (
    <div>
      <div ref={divRef}>
         <h3>app</h3>
         <button onClick={()=>{
            console.log(divRef.current);
         }}>获取DOM元素</button>
      </div>
    </div>
  );
}

4.useContext

作用 :获取从祖先组件传递给后代组件的数据

4.1.创建context对象

context.js 代码

import React from 'react'
// 1. 创建context对象,并暴露出去
const context = React.createContext() 
export default context
4.2.使用Provider组件包裹 组件, 并通过 value 绑定要传的数据

App.jsx 代码

import React from "react";
import Father from "./components/Father50";
import context from "./context";
export default function App() {
  return (
     // 2. 使用Provider包裹组件,并通过value绑定要传输的数据
    <context.Provider value={{ name: "App的内容" }}>
      <div>
        <h3>App</h3>
        <hr />
        <Father />
      </div>
    </context.Provider>
  );
}
4.3. 引入context对象
4.4.通过useContext处理context对象,获取祖先组件传递的数据
import React from 'react'

// 3. 引入context对象
import context from '../context'
import { useContext } from "react";

export default function Father() {
    // 4. 通过useContext处理context对象,获取祖先组件传递的数据
    let {name} = useContext(context)
    return (
        <div>
            <h4>Father</h4>
            <p>Father-context: {name}</p>
            <hr />
        </div>
    )
}

5.useReducer

集中状态管理。相当于是简化版的 redux

import React, { useState } from 'react'
import { useReducer } from 'react'
const initalState = { count: 0, msg: 'atguigu' }
function reducer(state, action) {
    switch (action.type) {
        case 'inc':
            return {
                ...state,
                count: state.count + 1
            }
        case 'dec':
            return {
                ...state,
                count: state.count - 1
            }
        case 'add':
            return {
                ...state,
                msg:state.msg + '+'
            }
        default:
            throw new Error('没有处理case')
    }
}
export default function App() {
    let [state, dispatch] = useReducer(reducer, initalState)
    return (
        <div>
            <p>count: {state.count}</p>
            <p>msg: {state.msg}</p>
            <p><button onClick={()=>{
                dispatch({type:'inc'})
            }}>count + 1</button></p>

            <p><button onClick={()=>{
                dispatch({type:'add'})
            }}>msg + '+'</button></p>
        </div>
    )
}

6.useCallBack

可以缓存一个函数。避免函数的多次创建。性能优化

用法一:

没有第二个参数,函数仍然会被重复创建

  let clickHandler = useCallback(() => {
    setCount(count + 1);
  });

用法二:

第二个参数是空数组,那么函数会被缓存

    let clickHandler = useCallback(()=>{
        // setCount(count + 1)
        // 函数被缓存,可以使用setXxx 第二种用法,获取最新的状态值
        setCount(count=>count + 1)
    },[])

用法三:

第二个参数是数组,并监听 x 个 状态,当这些状态中的一个或多个发生变化时,重新创建函数

  let clickHandler = useCallback(() => {
    setCount(count + 1);
    // 函数被缓存,可以使用setXxx 第二种用法,获取最新的状态值
    // setCount(count=>count + 1)
  }, [count]);

7.React.memo

作用:类似于类组件中的纯组件。当自身状态和外部数据没有变化的时候,不会重新渲染

App.jsx 代码

import React, { Component } from 'react'
import Test from './components/Test56'
export default class App extends Component {
    state = {
        msg:'React'
    }
    render() {
        console.log('App render')
        return (
            <div>
                <h3>App</h3>
                <p>msg: {this.state.msg}</p>
                <p><button onClick={()=>this.setState({
                    msg:'React'
                })}>msg change</button></p>
                <hr />
                <Test msg={this.state.msg}/>
            </div>
        )
    }
}

 Test.jsx 代码

import React from 'react'
import { useState } from 'react'

function Test({msg}) {
    console.log('Test render')
    // useState已经对自身状态做过优化
    let [count,setCount] = useState(0)
    return (
        <div>
            <p>count:{count}</p>
            <p>App-msg: {msg}</p>
            <button onClick={()=>{
                setCount(100)
            }}>count + 1</button>
        </div>
    )
}

export default React.memo(Test)

如图所示:

8.useMemo

作用:缓存一个函数计算的结果,常用来跟useCallback进行比较;useCallback是缓存一个 函数,useMemo缓存函数执行的结果

通俗来讲就是:它是一个优化性能的 Hook,它会记住函数的返回值,只要依赖项(dependency array)没有变化,就会复用之前的计算结果,避免在每次渲染时都重新执行这个可能开销较大的计算

官方详解:

App.jsx 代码

import React from 'react'
import Test from './components/Test57'

export default function App() {
    return (
        <div>
            <Test/>
        </div>
    )
}

Tset.jsx 代码

import React, { useState,useMemo } from 'react';

export default function Test() {
const [count,setCount] = useState(0)
const [val,setVal] = useState(0)

const expensive = useMemo(()=>{
    console.log('================');
    let sum =0
    for(let i=1;i<count;i++){
        sum += i
    }
    return sum
},[count])

// const expensive = (()=>{
//     console.log('================');
// },[count])

    return <div>
        <h4>{count}-{val}-{expensive}</h4>
        <div>
            <button onClick={()=>setCount(count + 1)}>+c1</button>
            <input val={val} onChange={event =>{
                setVal(event.target.value)
            }}/>
        </div>
    </div>;
}

9.useImperativeHandle

它与 forwardRef 结合使用以暴露自定义组件的 refs 给父组件。可以在使用 `ref` 时自定义暴露给父组件的实例值

官方文档:useImperativeHandle – React

APP.jsx 代码

import React from 'react'
import { useRef } from 'react'
import FunTest from './components/FunTest58'

export default function App() {
    // ref可以给绑定类组件,并且可以获取类组件实例对象
    let refClass = useRef()
    // ref本身不能够给函数组件使用,但是可以通过 React.forwardRef()进行扩展
    let refFn = useRef('true')
    /**
     * 当希望在父组件获取子组件的dom对象的时候,可以使用 函数组件配合 React.forwardRef()实现
     */
    return (
        <div>

            <FunTest ref={refFn} />

            <p><button onClick={() => {
                console.log(refClass)
                console.log(refFn)
            }}>获取ref</button></p>

            <p><button onClick={() => {
                refFn.current.changeBg()
            }}>changeBg</button></p>

            <p><button onClick={() => {
                refFn.current.changeFontSize()
            }}>changeBg</button></p>
        </div>
    )
}

FunTest.jsx 代码

import React from "react";
import { useRef, useImperativeHandle } from "react";

function FunTest(props, AppRef) {
  let selRef = useRef()
  
  useImperativeHandle(AppRef,()=>({
    changeBg:()=>{
        selRef.current.style.backgroundColor = "red"
    }
  }))

  return (
    <div>
      <h3 ref={selRef}>FunTest</h3>
    </div>
  );
}
export default React.forwardRef(FunTest);

 如图所示:

10.useLayoutEffect

useLayoutEffectuseEffect的一个版本,在浏览器重新绘制屏幕之前触发。

useEffect在render结束后,你的callback函数执行,但是不会阻塞浏览器渲染

作用:用在处理DOM的时候,当你的useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否 则可能会出现出现闪屏问题, useLayoutEffect里面的callback函数会在DOM更新完成后立即执行,但是会在 浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制

官方文档:useLayoutEffect – React

App.jsx 代码

import React from 'react'
import Animate from './components/Animate59'

export default function App() {
  return (
    <div>
        <Animate/>
    </div>
  )
}

Animate.jsx 代码

import React, { useEffect, useLayoutEffect, useRef } from 'react'
import TweenMax from 'gsap' // npm i [email protected]
import '../index.css'

const Animate = () => {
    const REl = useRef(null)

    useLayoutEffect(()=>{
        TweenMax.to(REl.current,0,{x:600})
    },[])
    return (
        <div className="animate">
            <div ref={REl} className="square">
                square
            </div>
        </div>
    )
}
export default Animate

11.useDebugValue

作用:用于在 React 开发者工具中显示 自定义 hook 的标签,只能在自定义hook中使用

官方文档:useDebugValue – React

12.useId

用于生成一个唯一的标识

import React from 'react'
import { useId } from 'react'

export default function App() {
  let id1 = useId()
  let id2 = useId()
  console.log(id1);
  console.log(id2);
  return (
    <div>
          <div>App</div>
    </div>
  )
}

 

13.useTransition

作用:可以将任务设置为非紧急任务

官方文档:useTransition – React

const [isPending, startTransition] = useTransition()
startTransition(()=>{
               
 })

14.useDeferredValue

作用:根据一个状态,设置一个延时的状态。也可以实现,任务渲染的优先级区别

import { useState, useDeferredValue } from 'react';

function SearchPage() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  // ...
}

15.自定义hook函数

作用: 函数组件代码逻辑复用的手段,函数名 useXxx 格式 ,函数中可以使用其他hook函数

App.jsx 代码

import React, {useState} from 'react'
import { useEffect } from 'react'
import usePosition from '../hook/usePosition'
export default function Cat() {
 let {x,y} = usePosition()
 return (
 <div style={{width:100,height:100,border:'1px solid red',position:'absolute',left:x,top:y}}>Cat</div>
 )
}

 usePosition.js 代码

import {useState, useEffect} from 'react'
export default function usePosition() {
 let [x, setX] = useState(0)
 let [y, setY] = useState(0)
 function moveHandler(e) {
 setX(e.clientX)
 setY(e.clientY)
 }
 useEffect(() => {
 window.addEventListener('mousemove', moveHandler)
 return () => {
 window.removeEventListener('mousemove', moveHandler)
 }
 }, [])
 return {x,y}
}

标签:count,react,函数,React,Hook,组件,import
From: https://blog.csdn.net/qq_44866810/article/details/136843520

相关文章

  • 【安卓漏洞挖掘】drozer--安卓四大组件的漏洞学习
    drozer:drozer(以前称为Mercury)是一款强大的开源Android安全评估框架,旨在帮助安全研究人员和渗透测试人员发现并利用Android设备和应用程序中的潜在安全漏洞。通过drozer,用户可以在设备上或远程执行一系列安全测试,包括但不限于:访问及控制本地应用:通过API探索和操作已安装的应用程序......
  • 将自己写的组件封装成类似element-ui一样的库,可以cdn引入
    在写好自己的组件之后第一步修改目录结构在根目录下创建package文件夹,用于存放你要封装的组件第二步在webpack配置中加入pages与publicpath同级pages:{index:{entry:'src/main.js',template:'public/index.html',......
  • 深入理解 SpringAOP(一):AOP 组件概述
    概述spring-aop模块是Spring框架中最重要的组件之一,它为我们提供了强大的AOP功能,并为其他扩展功能(如声明式事务、声明式异步处理等)提供了支持。在本文中,我们将深入探讨SpringAOP的源码,从代理对象的创建开始,揭示SpringAOP的运行机制。首先,在阅读这篇文章前,请先确保对Sp......
  • Salesforce LWC学习(四十九) RefreshView API实现标准页面更新,自定义组件自动捕捉更新
    本篇参考: https://developer.salesforce.com/docs/platform/lwc/guide/data-refreshview.htmlhttps://developer.salesforce.com/docs/platform/lwc/guide/reference-lightning-refreshview.htmlhttps://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007KX6dA......
  • 前端学习-vue视频学习011-自定义hooks
    尚硅谷视频链接axios了解了一下axios的语法importaxiosfrom'axios'exportdefaultfunction(){letdogList=reactive(['https://images.dog.ceo/breeds/pembroke/n02113023_4972.jpg'])asyncfunctiongetDog......
  • 在非标准Spring组件中(比如websocket)注入Spring管理bean的方法
    privatestaticUserMapperuserMapper;@AutowiredpublicvoidsetUserMapper(UserMapperuserMapper){WebSocketServer.userMapper=userMapper;}WebSocketServer是通过JavaWebSocketAPI创建的,并且由于@ServerEndpoint不是Spring的标准组件注解,直......
  • VUE3 十种组件通信的方式(附详细代码)
    props用途:可以实现父子组件、子父组件、甚至兄弟组件通信父组件<template><div><Son:money="money"></Son></div></template><scriptsetuplang="ts">importSonfrom'./son.vue'import{re......
  • 【Vue3】组件通信以及各种方式的对比
    方式一:props「父」向「子」组件发送数据父组件:定义需要传递给子组件的数据,并使用v-bind指令将其绑定到子组件的props上。<template><child-component:message="parentMessage"/></template><scriptsetup>importChildComponentfrom'./ChildComponent.......
  • 微信小程序(vantWeapp) UI组件库
     vantWeapp官方文档: https://youzan.github.io/vant-weapp/#/quickstart 根据文档的安装步骤  为什么写这样的变量名就能实现对相关的组件修改自定义颜色呢? 原因如下:根据文档描述,官方提供了相关的变量对应的组件 https://github.com/youzan/vant-weapp/blo......
  • react 开发一个 类似于条件筛选的组件 如下
     最终效果: 记录一下其中要点: 1.react 的数据被useState后,都不允许直接修改,都需要使用hooks才可以修改       2. useState必须要放到组件渲染函数中     3. 在jsx中不允许使用if 除了三元运算符和isChecked为真假来做标识符外......