React hooks API详情

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

hook 是react 16.8的新增特性 ,他可以让你不在编写class的情况下shiystate以及react的特性
Hooks的出现,首先解决了以下问题:
  1. 告别了令人疑惑的生命周期
  2. 告别类组件中烦人的this
  3. 告别繁重的类组件,回归到了熟悉的函数组件
react 整个思想上面的转变,从“面向对象”的思想转为“函数式编程”,所以你会突然发现会多了一些新概念 比如:纯函数,副作用,柯里化,高阶函数等概念
 

useState 

 

 1.基础使用

import { useState } from 'react'
function App() {
    // 参数:状态初始值比如,传入 0 表示该状态的初始值为 0
     返回值:数组,包含两个值:1 状态值(state) 2 修改该状态的函数(setState)
    const [count,setCount] = useState(0);
       修改count内容
    const modifyEvent = () => {
        setCount(count + 1)
    }
    return (
        <button onClick={() => modifyEvent()}>{count}</button>
    )
}
export default App

 

 2.状态的读取和修改执行流程与逻辑

  读取状态:该方式提供的状态,是函数内部的局部变量,可以在函数内的任意位置使用
  修改状态:

    1.setCount是一个函数,参数表示最新的状态值

    2.调用该函数后,将使用新值替换旧值

    3.修改状态后,由于状态发生变化,会引起试图变化 注意

  事项:修改状态的时候,一定要使用新的状态替换旧的状态,不能直接修改旧的状态,尤其是引用类型

 

3. 组件的更新过程

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

  1.组件第一次渲染

  • 从头开始执行该组件中的代码逻辑
  • 调用 useState(0) 将传入的参数作为状态初始值,即:0
  • 渲染组件,此时,获取到的状态 count 值为: 0

  2.组件第二次渲染

  • 点击按钮,调用 setCount(count + 1) 修改状态,因为状态发生改变,所以,该组件会重新渲染
  • 组件重新渲染时,会再次执行该组件中的代码逻辑
  • 再次调用 useState(0) ,此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 1
  • 再次渲染组件,此时,获取到的状态 count 值为:1
注:useState 的初始值(参数)只会在组件第一次渲染时生效。也就是说,以后的每次渲染,useState 获取到都是最新的状态值,React 组件会记住每次最新的状态值 
import { useState } from 'react'
 
 App() {
  const [count,setCount] = useState(0)
   在这里可以进行打印
  console.log(count,'渲染了')
   (
    <button onClick={() => { setCount(count + 1) }}>{count}</button>
  )
}
export default App

 4.使用规则

  1.useState 函数可以执行多次,每次执行互相独立,每调用一次为函数组件提供一个状态
 List(){
   以字符串为初始值
  const [name,setName] = useState('cp' 以数组为初始值
  const [list,setList] = useState([])
}

  2.useState 注意事项

  • 只能出现在函数组件或者其他hook函数中
  • 能嵌套在if/for/其它函数中(react按照hooks的调用顺序识别每一个hook)

 

useEffect

1.理解函数副作用

   副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
  常见的副作用:
  • 数据请求 ajax发送
  • 手动修改dom
  • localstorage操作
  useEffect函数的作用就是为react函数组件提供副作用处理的数据和逻辑,从而修改UI和用户交互等一种方式。
 

2. 基础使用

下面案例说明,函数组件储存了当前state所有状态,函数初次就会触发他们两个的加载,另外当某一个发生改变了 useEffect和函数都会被重新执行加载

import { useEffect,useState } from 'react'
 
)
 
  useEffect(()=>{
     修改了dom数据后 userffect函数被副作用重新执行
    console.log('执行了副作用函数')
  });
     函数组件也会被重新执行   
  console.log('函数组件被重新执行了'  )
}
 
export default App

 

3.useEffect依赖项和控制执行的时机

由于 组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行
 
添加空数组依赖
import { useEffect,useState } from 'react'
)
  useEffect(()=> 修改了dom数据后 userffect函数不会在被触发,只有首次加载函数才会执行一次
    console.log('执行了副作用函数')
  },[]);
    修改了dom数据后 函数组件会被重新执行   
  console.log('函数组件被重新执行了'default App

添加特定项作为依赖

副作用函数在首次渲染时执行,在依赖项发生变化时重新执行

给useEffect添加特定的依赖项,当这个依赖性的state发生改变,useEffect与函数组件都会重新渲染被执行,由于第二个参数是依赖项所以是数组可以添加多个依赖项

没有useEffect添加的特定的依赖项,就不会触发useEffect函数,只会触发组件的渲染函数

 App() {  
    const [count,1)">)  
    const [name,setName] = useState('zs') 
    
    useEffect(() => {    
        console.log('副作用执行了')  
    },[count])  
    console.log('组件被执行了')
     (    
        <>      
         <button onClick={() => { setCount(count + 1) }}>{count}</button>      
         <button onClick={() => { setName('cp') }}>{name}</button>    
        </>  
    )
}

清理副作用

 
 App() {
    const [count,1)">)
    const [name,1)">)

    useEffect(() => {
        console.log('副作用执行了')
        return () => {
            alert(1)
            console.log('执行了清楚副作用,组件卸载的时候执行')
        }
    },[count])
    console.log('组件被执行了' (
        <>
            <button onClick={() => { setCount(count + 1) }}>{count}</button>
            <button onClick={() => { setName('cp') }}>{name}</button>
        </>
    )
}

 

另外一般一个 useEffect 只用来处理一个功能,有多个功能时,建议使用多个 useEffect
 

useMemo(性能优化)

解决函数组件的性能问题,比如子组件重复执行问题,每次渲染都进行高开销的计算

 子组件
 Sub(props) {
    console.log("Sub render");
    let { number,onClick } = props
     (
        <button onClick={onClick}>{number}</button>
    )
}
 父组件
 Test() {
    let [value,setvalue] = useState('')
    let [number,setNumber] = useState(0)
    const addClick = () => setNumber(number + 1return <>
        <input type="text" value={value} onChange={(e) => setvalue(e.target.value)} />
        <Sub number={number} onClick={addClick} />
    </>
}

export default Test;

子组件依赖的只有number ,理想情况下只希望number变化时触发子组件重新渲染

但实际是在输入框内的值发生变化,子组件也会重新渲染 如果子组件的逻辑较复杂,就是无意义的大量计算,浪费资源

 使用useMemo记住计算后的值,只有当依赖number变量发生变化,才会重新计算子组件内容
    const MemoSub = useMemo(
        () => <Sub data={number} onClick={addClick} />,[number]  只有 number 变化才重新计算 MenoSub
      )
    return <>
        <input type="text" value={value} onChange={(e) => setvalue(e.target.value)} />
        {MemoSub}
    </>
default Test;

 

useCallback(性能优化)

接收两个参数:回调函数和依赖项数组。回调函数是需要缓存的函数,依赖项数组用于确定何时需要重新创建函数实例。

当依赖项数组中的任何一个值发生变化时,useCallback 将返回一个新的函数实例,否则它将返回之前缓存的函数实例

import { useState,useCallback } from 'react';

 MyComponent() {
  const [count,1)">);

   使用 useCallback 缓存 handleclick 函数
  const handleclick = useCallback(() => {
    setCount(count + 1);
  },[count]);

   (
    <div>
      <p>You clicked {count} times</p>
      {/* 在按钮上使用缓存的 handleclick 函数 */}
      <button onClick={handleclick}>Click me</button>
    </div>
  );
}

在这个例子中,我们使用 useCallback 来缓存回调函数 handleclick, 将其缓存以避免在每次重新渲染组件时创建新的函数实例。

同时,在按钮上使用了缓存的 handleclick 函数,以确保点击按钮时调用的是缓存的函数实例。我们还将 count 添加到依赖项数组中,以确保每当 count 发生变化时,handleclick 都会被重新创建。

useCallback 和 useMomeo 的区别

1.useCallback 和 useMemo 都是用于性能优化的 React 钩子函数,它们都可以避免不必要的重新计算或重新渲染。虽然它们看起来很相似,但它们有几个重要的区别。

2.首先,useCallback 返回一个缓存的回调函数,而 useMemo 返回一个缓存的值。这意味着 useCallback 的主要作用是为一个函数创建缓存,而 useMemo 的主要作用是缓存一个值

3.最后,它们的使用场景也不同。useCallback 适用于优化回调函数,避免不必要的重新渲染,并传递给子组件。而 useMemo 适用于优化计算开销较大的值,如大型数组或对象的计算

 

useRef

useRef 可以缓存所有数据类型,更新的数据不会随着组件的重新渲染而重置,会一直保持最新状态的内容,

但是保存的数据类型 无法在ui渲染页面上使用,只能作为一个状态进行储存

也可以绑定给一个元素标签获取dom进行操作

 Test() {
     保存 DOM 
    const inputEl = useRef()
    const onClick = () => {
        console.log(inputEl);  对象类型,只有一个 current 属性指向指定DOM
        inputEl.current.innerHTML = '2asdasd sd阿萨德'
    }

    return <div>
        <div ref={inputEl}></div>
        <button onClick={onClick}>click me!!!</button>
        <br />
    </div>
}

 

useContext

usecontext React 16.3本中新引入的一个特性,它可以让组件之间共享数据十分方便。它属于 React Context API(上下文API),可以让组件层级之间自由传递数据,而使用Context API可以极大地提高组件之间的可复用性。
使用 useContext以使组件树中的任何组件访问到 cntext值,无论它是何种层级的,而且更方便的是,不需要利用props行传递,而只需要一行代码即可

下面案例是同一组件下多个 子组件的上下文通讯

import React,{ createContext,useContext } from 'react';

const ThemeContext = createContext('light')
 Test() {
   (
    <ThemeContext.Provider value="dark">
      <Toolbar theme="dark" />
    </ThemeContext.Provider>
  )
}
 Toolbar(props) {
   (
     中间的组件再也不必指明往下传递 theme 了。
    <div>
      <Button />
    </div>
 子组件中的子组件
 Button() {
   指定 contextType 读取当前的 themecontext。
   React 会往上找到最近的 theme Provider,然后使用它的值。
   在这个例子中,当前的 theme 值为 “dark”。
  const theme = useContext(ThemeContext)
  return <button>{ theme }</button>
}

 

垮文件使用usecontext 进行通讯

 父组件

import React,{ useState,createContext } from 'react'
import Counter from './Counter'
 
export const countContext = createContext()
 
export default  Example4() {
    const [count,1)"> (
        <div>
            <p>你点击了{count}次</p>
            <button onClick={()=>{setCount(count+1)}}>点击</button>
            <countContext.Provider value={count}>
                <Counter />
            </countContext.Provider>
        </div>
    )
}

子组件

import React,{ useContext } from 'react'
import { countContext } from './Example4'
 
 Counter() {
    let count = useContext(countContext)
     (
        <div>
            <h2>{count}</h2>
        </div>
    )
}
 
export default Counter

 

 这样在多级组件使用就减少使用redux,useContext确实好用,起码跨级传递数据不用那么麻烦了

 

 完结,有不足欢迎补充。

 
 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件举报,一经查实,本站将立刻删除。

本文链接:https://www.f2er.com/3188639.html

大家都在看

  • 飞码LowCode前端技术系列:如何便捷快速验证实现投产及飞码探索

    本篇文章从数据中心,事件中心如何协议工作、不依赖环境对vue2.x、vue3.x都可以支持、投产页面问题定位三个方面进行分析。
    2023-11-16 博文
  • 如何优雅使用 vuex

    大纲 本文内容更多的是讲讲使用 vuex 的一些心得想法,所以大概会讲述下面这些点: Q1:我为什么会想使用 vuex 来管理数据状态交互? Q2:使用 vuex 框架有哪些缺点或者说副作用? Q3:我是如何在项目里使用 vuex 的? 初识 vuex 对于 vuex,有人喜欢,有人反感 喜欢的人觉
    2023-11-16 博文
  • 第三方组件及计算属性传参的问题解决方式

    1. 前言 唉,好想玩滋嘣。 2. 计算属性直接传参接收不到 表格数据某一列需要用的计算属性时,模板中使用计算属性 fullName 就会直接调用 fullName 函数,而在模板中 fullName(item) 相当于fullName()(item),此处为函数柯里化。 &lt;el-table-
    2023-11-16 博文
  • 记录--Vue3基于Grid布局简单实现一个瀑布流组件

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 在学习Grid布局之时,我发现其是CSS中的一种强大的布局方案,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,在刷某书和某宝首页时,我们发现其展示方式就是一种瀑布流,是一种流行的网站页面布局,视觉表……
    2023-11-16 博文
  • 用强数据类型保护你的表单数据-基于antd表单的类型约束

    接口数据类型与表单提交数据类型,在大多数情况下,大部分属性的类型是相同的,但很少能做到完全统一。我在之前的工作中经常为了方便,直接将接口数据类型复用为表单内数据类型,在遇到属性类型不一致的情况时会使用any强制忽略类型错误。后来经过自省与思考,这种工作模式会引起各种隐藏bug,一定有更……
    2023-11-16 博文
  • pinia的使用

    前言 最近新开了个项目,以前老项目都是vue2+vuex开发的,都说用vue3+pinia爽得多,那新项目就vue3+pinia吧。这里记录一下pinia的使用。 使用方法 安装pinia: npm i pinia main.js中引入pinia: //main.js import { create
    2023-11-16 博文
  • 记录--让我们来深入了解一下前端“三清”是什么

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前端“三清” 在前端开发中,我们经常听到关于“三清”的说法,即 window、document、Object。这三者分别代表了 BOM(浏览器对象模型)、DOM(文档对象模型)以及 JS 的顶层对象。在这个体系中,我们通过 JavaScr
    2023-11-16 博文
  • 记录--啊?Vue是有三种路由模式的?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 众所周知,vue路由模式常见的有 history 和 hash 模式,但其实还有一种方式-abstract模式(了解一哈~) 别急,本文我们将重点逐步了解: 路由 + 几种路由模式 + 使用场景 + 思考 + freestyle 路由概念
    2023-11-16 博文