React Hooks钩子中API的使用示例分析

目录
  • hooks是什么
  • Hooks的作用
  • 使用Hooks组件前后开发模式的对比
  • Hooks使用策略
  • 为什么要有Hooks
  • useState
  • useEffect使用
    • useEffect依赖项
    • 使用情景
  • useMemo使用
    • useMemo缓存组件方式
    • useMemo和useEffect的区别
  • useCallback使用
  • useContext使用
  • useRef使用
    • 为什么在函数组件中无法使用ref
    • 如何在类组件中使用ref属性
  • 自定义hooks

hooks是什么

hooks理解字面意思就是钩子,是一些可以让你在函数组件里钩入 React state以及生命周期等特性的函数,可以让不编写class的情况下使用state以及其他的React特性

Hooks的作用

为函数组件提供状态,生命周期等原本在class组件中才提供的功能

Hooks只能在函数组件中使用

可以理解为通过Hooks为函数组件钩入class组件的特性

使用Hooks组件前后开发模式的对比

使用前(React v 16.8前):class组件(提供状态)+函数组件(展示内容)

使用后(React v 16.8后):Hooks(提供状态)+函数组件(展示内容)

Hooks使用策略

(1)react没有计划从React中移除class

(2)hook和现有代码可以同时工作,可以渐进式使用

不推荐直接使用Hooks大规模重构现有组件

推荐新功能使用Hooks,复杂功能实现不来,也可以继续使用class

(3)class组件相关的API在hooks里面可以不用

state setState 钩子函数,this相关用法

(4)原来学习的内容还是要用

JSX:{} onClick={} 、条件渲染、列表渲染、样式处理

组件:函数组件,组件通讯

react开发理念:单向数据流,状态提升

为什么要有Hooks

首先我们要了解react的本质,接着从函数组件和类组件进行分析优缺点

react本质:用于构建用户界面的javascript库,是对特定功能的封装,主要对url进行拆分

react组件的模型其实很直观,就是从model到view的映射,这里的model对应的是react的state和props

函数式组件的好处:

  • 函数本身比较简单,更好的胜任根据状态来渲染url这件事
  • hooks让函数组件内部有了维护状态的能力
  • hooks带来了组件的逻辑复用的能力

class组件自身的问题:

  • 在根据状态来渲染url这件事上,class组件并没有发挥它的重要功能
  • 组件之间很少继承
  • 组件之间很少相互访问

useState

作用:为函数组件提供state状态

步骤:

  • 导入useState函数
  • 调用useState函数,传入初始值,返回状态和修改状态的函数
  • 使用:在jsx中展示状态,特定的时机调用修改状态的函数修改状态
  • 定义state数据,返回一个数组,有两个值,第一个值,定义数据初始化的值,第二个值,修改数据函数,可以做到页面的响应式

useState两种格式:

格式1:传入值 useState(0) 或useState('abc')

格式2:传入回调,useState({上一次的值}=>{return 新值})

  • 回调函数的返回值就是状态的当前值
  • 回调函数只会触发一次

代码展示

import React, { useState } from 'react'
export default function UseState() {
    let [count,setCount]=useState(10)
    // 他是异步的操作,在页面数据会进行更新,但是下面打印的数据是没有更新,原因是因为他是异步的
    const plus=()=>{
        setCount(count+5)
    }
  return (
    <div>
        {/* 函数组件中没有this指向,我们可以直接调用 */}
        <div>{count}</div>
        <button onClick={()=>setCount(count++)}>加加</button>
        <button onClick={plus}>plus</button>
    </div>
  )
}

注意:上面必须引入useState 使用

useEffect使用

函数式组件:

主作用:就是根据数据(state/props)渲染ul

副作用:数据请求,手动修改DOM、开启定时器、清空定时器、localStorage操作等

副作用:只要是渲染数据之外的操作都是副作用,副作用不一定非要写在useEffect里,可以写外面,但是写useEffect会起到约束作用

执行时机(以下两种情况会执行Effect):

  • 组件挂载时,执行一次(相当于生命周期中componentDidMount)
  • 组件更新时,可能执行多次(相当于生命周期中的componentDidUpdate)

在实际开发中,副作用是不可避免的,react专门用useEffect来处理组件中的副作用

useEffect依赖项

有两个参数:(参数一:(副作用函数),参数二:(执行副作用函数的依赖项,他决定了什么时候执行参数1(副作用)))

  • 如果不设置第二个参数,那么每次页面更新他都会执行
  • 参数是空数组,永远只执行第一次
  • 指定依赖项,执行时机(初始化执行一次,依赖项发生变化执行一次)可以有多个依赖项
  • useEffect() 代替三个生命周期函数 componentDidMount compoentDidUpdate 钩子函数, componentWillUnmount 生命周期

使用情景

  • 事件绑定
  • 发送请求获取数据等 axios ajax
useEffect(()=>{ 逻辑})  页面数据只要更新就会触发useEffect()
useEffect(()=>{},[])  useEffect() 只执行一次,只有页面第一次加载的时候触发,componentDidMount
useEffect(()=>{}, [num,count]) 监听数据改变执行,num和count发生变化的时候触发。compoentDidUpdate
useEffect(()=>{
    return ()=>{
        console.log("相当于compoentDidUnmount")
    }
},[])
//回调函数返回函数,返回的函数相当于销毁生命周期函数。

useMemo使用

相当于vue中计算属性,他一般需要返回一个结果,具有缓存性的效果

useMemo他是在DOM更新的时候触发的,useEffect() DOM更新后触发的副作用函数

缓存复杂运算的结果,避免重复调用执行

useMemo页面一般会渲染第一次执行后的结果

代码展示

import React, { useMemo, useState } from 'react'
export default function UseState() {
    let [count,setCount]=useState(10)
    // useMemo必须有返回值,而且他是在dom更新发生变化,比useEffect执行的快,useEffect是dom更新完才执行的,监听count值变化
    const double=useMemo(()=>{
      console.log('useMemo触发');
      return count+6
    },[count])
  return (
    <div>
        {/* 函数组件中没有this指向,我们可以直接调用 */}
        <div>{count} {double}</div>
        <button onClick={()=>setCount(count*2)}>count二倍</button>
    </div>
  )
}

useMemo缓存组件方式

第一种通过useMemo缓存组件

//useMemoe缓存组件
function Home() {
    let [count,setcount] = useState(10)
    let [num,setnum] = useState(20)
    //通过useMemoe对组件进行缓存,避免父组件中根子组件无关数据更新导致子组件的重新渲染。
    let theme = useMemo(()=>{
        return (
            <Theme count={count}></Theme>
        )
    },[count])
    return (
        <div>
            <h3 >count--{count}</h3>
            <button onClick={()=>setcount(count+1)}>count++</button>
            <h3 >num--{num}</h3>
            <button onClick={()=>setnum(num+1)}>num++</button>

            <hr />
            {theme}
        </div>
    )
}
function Theme(props){
    useEffect(()=>{
        console.log("子组件渲染")
    });
    return (
        <h3>子组件接受数据{props.count}</h3>
    )
}

第二种通过react自带的memo方法

memo是一个高阶组件方法,接受一个组件作为参数,根据组件传递的参数值,对组件进行缓存,避免组件的多余的DOM渲染效果

function Home() {
    let [count,setcount] = useState(10)
    let [num,setnum] = useState(20)
    return (
        <div>
            <h3 >count--{count}</h3>
            <button onClick={()=>setcount(count+1)}>count++</button>
            <h3 >num--{num}</h3>
            <button onClick={()=>setnum(num+1)}>num++</button>
            <hr />
            <Theme count={count}></Theme>
        </div>
    )
}
 //通过memo对组件进行缓存,避免父组件中根子组件无关数据更新导致子组件的重新渲染。
const Theme = memo((props)=>{
    useEffect(()=>{
        console.log("子组件渲染")
    });
    return (
        <h3>子组件接受数据{props.count}</h3>
    )
})

useMemo和useEffect的区别

不同点:

useEffect是在dom更新后触发的副作用函数,他被称为副作用函数就是因为他在我们更新完成之后才通知我们,类似于马后炮,useEffect不需要返回值,他没有数据缓存的作用

useMemo是在dom更新时触发的,useMemo必须要返回数据的结果,他是具有缓存数据的作用

共同点:

如果非要说共同点,那么他俩都有两个参数,并且第二个参数如果是空[]的话,那么他的数据只会执行一次,也可以给他设置监听项,[监听值的名称],第二个参数是可选参数,也可以不写,不写就是页面只要发生一点改变,就会重新渲染一次,浪费数据更新的性能

useCallback使用

在上述的例子中如果我们传递的是普通的变量,缓存后,父组件更新的话不会导致子组件的更新,但是如果你传递的是一个函数,父组件的每次更新都会重新调用一次函数,这个时候就会不同函数调用,会导致子组件的重新渲染,如果我们还要做组件缓存,我们可以使用useCallback() , 可以对函数进行一个缓存的作用

代码展示

function Home() {
    let [count,setcount] = useState(10)
    let [num,setnum] = useState(20)
    const handlerCount = ()=>{
        console.log(count);
    }
    const callback = useCallback(()=>{
        handlerCount();
    },[count]);
    return (
        <div>
            <h3 >count--{count}</h3>
            <button onClick={()=>setcount(count+1)}>count++</button>
            <h3 >num--{num}</h3>
            <button onClick={()=>setnum(num+1)}>num++</button>

            <hr />
            <Theme count={count} handle={callback}></Theme>
        </div>
    )
}
 //通过memo对组件进行缓存,避免父组件中根子组件无关数据更新导致子组件的重新渲染。
const Theme = memo((props)=>{
    useEffect(()=>{
        console.log("子组件渲染")
    });
    return (
        <div>
             <h3>子组件接受数据{props.count}</h3>
             <button onClick={()=>props.handle()}>点击</button>
        </div>
    )
})

useMemo,memo,useCallback如何提升性能的(面试题必问)?

useMemo主要的作用是缓存复杂运算的数据返回的结果,有两个参数,第二个参数可以定义要监听的数据,并且需要返回,跟useEffect第二个参数的作用类同

当父组件的组件更新的时候会导致子组件的重新渲染,但是如果父组件的更新的数据没有传递给子组件的话,这时候还让子组件重新渲染的话,会导致组件更新性能消耗比较大

所以说这个时候我们可以使用useMemo,或者使用react内置的memo方法对子组件进行缓存,这样只有父组件更新跟子组件有关的数据时才会导致子组件重新渲染,从而提高组件的渲染性能

但是如果我们给子组件传递的是一个方法的时候,上面的useMemo,memo方法缓存就不起作用了,原因是父组件每更新一次会导致方法的重新调用,进而导致子组件的重新更新,这时候我们可以用到useCallback对传递的方法进行缓存,监听数据更新后才会重新调用方法,从而提高组件的渲染性能

useContext使用

用来获取context状态树的内容数据的Hooks的APi,相当于class组件中static contextType = react.createContext创建的对象内容

代码展示

import React, { useContext, useState } from 'react';
//useContext用于获取context状态树的值
// 首先创建一个空的context对象
const ThemContext =React.createContext();
function UseState() {
    let [color,setColor]=useState('#ff0000')
  return (
    <div>
      {/* 通过Provider传过来一个value值,是一个对象 */}
       <ThemContext.Provider value={{color:color}}>
          <button onClick={()=>setColor('pink')}>粉色</button>
          <button onClick={()=>setColor('blue')}>蓝色</button>
          <button onClick={()=>setColor('green')}>绿色</button>
          <Son></Son>
       </ThemContext.Provider>
    </div>
  )
}
// 子组件
function Son(props) {
  // 通过useContext获取父组件传过来的值
  const context=useContext(ThemContext)
  return (
    <div>
      {/* 然后对他进行样式绑定 */}
      <h3 style={context}>hello,react</h3>
    </div>
  )
}
export default UseState

useRef使用

useRef 作用相当于class组件React.createRef()的作用,用于创建ref节点对象的内容

 //创建一个ref对象的内容
    let inp = useRef(null);
    const setVal =()=>{
        console.log(inp.current.value);
    }
   <input placeholder='输入内容' ref={inp} onChange={setVal}/>

为什么在函数组件中无法使用ref

普通的类组件有实例所以可以用React。createRef()挂载到节点或者组件上,然后通过this获取到该节点或组件,正常情况下ref是不能挂到函数组件上,因为函数组件没有实例

如何在类组件中使用ref属性

我们可以通过forwardRef将ref父类的ref作为参数传入函数式组件中

forwardRef是一个高阶函数,跟memo一样

还有一种方法就是把函数组件改成类组件

function Home() {
    //定义一个初始化变量
    let inpRef = useRef(null);
    const getTheme = ()=>{
        console.log(inpRef);
    }
    return (
        <div>
             <input placeholder='输入内容'/>
             <button onClick={getTheme}>获取子组件对象</button>
             <hr />
             <Theme ref={inpRef}/>
        </div>
    )
}
const Theme = forwardRef(function(props,ref){
    return (
        <h3 ref={ref}>文字内容显示</h3>
    )
})

自定义hooks

写一个自定义页面标题的效果,路由中使用

import { useEffect } from "react";
//自定义显示标题的Hooks的方法内容
const useTitle = (title) => {
    useEffect(() => {
        document.title = title;
        return ()=>{
            document.title="React 页面"
        }
    }, []);
    return;
}
export { useTitle };
import { useTitle } from "../context/hooksApi"
export default function My(){
    useTitle("个人中心")
    return (
        <div>
            <h3>个人中心</h3>
        </div>
    )
}

还有其他的自定义hooks API方法,这举例的是一种

到此这篇关于React Hooks钩子中API的使用示例分析I的文章就介绍到这了,更多相关React Hooks API内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • React中的Hooks进阶理解教程

    目录 Hooks进阶 useState - 回调函数的参数 useEffect - 清理副作用 useEffect - 发送网络请求 useRef useContext Hooks进阶 useState - 回调函数的参数 使用场景 参数只会在组件的初始渲染中起作用,后续渲染时会被忽略.如果初始 state 需要通过计算才能获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用 语法 const [name, setName] = useState(()=>{

  • 三分钟搞懂react-hooks及实例代码

    目录 背景 useState 类组件 函数组件 多状态声明 useEffect 类组件中componentDidMount和componentDidUpdate useEffect模拟类组件中componentDidMount和componentDidUpdate useEffect实现componmentWillUnment 父子组件传值useContext useReducer 背景 介绍Hooks之前,首先要说一下React的组件创建方式,一种是类组件,一种是纯函数组件,并且React团队

  • React hooks useState异步问题及解决

    目录 React Hooks useState异步问题 原因 解决方法 React中useState异步更新小坑 问题点 React Hooks useState异步问题 最近在开发中遇到一个问题 我接口请求回来的数据 用useState存储起来. 但是我后面 去改变这个数据的时候每次拿到都是上次的数据没办法及时更新. 原因 useState 返回的更新状态方法是异步的,要在下次重绘才能获取新值.不要试图在更改状态之后立马获取状态. 解决方法 应该使用useRef 存储这个数据,在useEffe

  • Jetpack Compose对比React Hooks API相似度

    目录 React Component vs Composable JSX vs DSL loop If statement key component Children Prop vs Children Composable Context vs Ambient(CompositionLocal) createContext : ambientOf Provider : Provider useContext : Ambient.current useState vs State useMemo

  • 使用 React Hooks 重构类组件的示例详解

    目录 1. 管理和更新组件状态 2. 状态更新后的操作 3. 获取数据 4. 卸载组件时清理副作用 5.  防止组件重新渲染 6. Context API 7. 跨重新渲染保留值 8. 如何向父组件传递状态和方法? 9. 小结 最初,在 React 中可以使用 createClass 来创建组件,后来被类组件所取代.在 React 16.8 版本中,新增的 Hooks 功能彻底改变了我们编写 React 程序的方式,使用 Hooks 可以编写更简洁.更清晰的代码,并为创建可重用的有状态逻辑提供了

  • 详解React hooks组件通信方法

    目录 一.前言 二.父子组件通信 1)父组件传值给子组件 2)子组件传值给父组件 3)跨组件传值(父传孙子组件) 一.前言 组件通信是React中的一个重要的知识点,下面列举一下 react hooks中常用的父子.跨组件通信的方法 二.父子组件通信 1)父组件传值给子组件 子组件代码: //子组件 const Child = ({ param1, param2 }) => { return <>父组件传递的参数:{param1},{param2}</> } param1.p

  • React-hooks中的useEffect使用步骤

    目录 1.理解函数副作用 什么是副作用? 常见的副作用 2.基础使用 使用步骤 示例代码 3.依赖项控制 useEffect 永远是在 DOM渲染完成之后执行 1.理解函数副作用 什么是副作用? 对于React组件来说,主作用是根据数据(state/props)渲染UI,除此之外都是副作用(比如手动修改DOM.发送ajax请求). 常见的副作用 数据请求(发送ajax) 手动修改 DOM localstorage操作 useEffect 函数的作用就是为react函数组件提供副作用 2.基础使用

  • 进入Hooks时代写出高质量react及vue组件详解

    目录 概述 1.组件什么时候拆?怎么拆? 2.如何组织拆分出的组件文件? 3.如何用hooks抽离组件逻辑? 题外话:全局状态的管理 概述 vue和react都已经全面进入了hooks时代(在vue中也称为组合式api,为了方便后面统一称为hooks),然而受到以前react中类组件和vue2写法的影响,很多开发者都不能及时转换过来,以致于开发出一堆面条式代码,整体的代码质量反而不如改版以前了. hooks组件到底应该如何写,我也曾为此迷惘过一段时间.特别我以前以react开发居多,但在转到新岗

  • react hooks闭包陷阱切入浅谈

    目录 引言 1.一个熟悉的闭包场景 2 浅谈hooks原理,理解useEffect 的 “闭包陷阱” 出现原因 2 难道真的要在依赖数组里写上的值,才能拿到新鲜的值? 3 为什么使用useRef能够每次拿到新鲜的值? 4 完毕 引言 首先,本文并不会讲解 hooks 的基本用法, 本文从 一个hooks中 “奇怪”(其实符合逻辑) 的 “闭包陷阱” 的场景切入,试图讲清楚其背后的因果.同时,在许多 react hooks 奇技淫巧的文章里,也能看到 useRef 的身影,那么为什么使用 useR

  • React Hooks钩子中API的使用示例分析

    目录 hooks是什么 Hooks的作用 使用Hooks组件前后开发模式的对比 Hooks使用策略 为什么要有Hooks useState useEffect使用 useEffect依赖项 使用情景 useMemo使用 useMemo缓存组件方式 useMemo和useEffect的区别 useCallback使用 useContext使用 useRef使用 为什么在函数组件中无法使用ref 如何在类组件中使用ref属性 自定义hooks hooks是什么 hooks理解字面意思就是钩子,是一些

  • React Context原理深入理解源码示例分析

    目录 正文 一.概念 二.使用 2.1.React.createContext 2.2.Context.Provider 2.3.React.useContext 2.4.Example 三.原理分析 3.1.createContext 函数实现 3.2. JSX 编译 3.3.消费组件 - useContext 函数实现 3.4.Context.Provider 在 Fiber 架构下的实现机制 3.5.小结 四.注意事项 五.对比 useSelector 正文 在 React 中提供了一种「

  • 停止编写 API函数原因示例分析

    目录 正文 你可能会问为什么?有一些很好的理由: 一个非常简单的 CRUD 构造器 高级 CRUD 构造器 过滤 转换和分页 准备 自定义接口 最终的 BRUD 构造器 正文 RESTFUL API 通常提供在不同实体上执行增删改查(CRUD)操作的一组接口.我们通常在我们的前端项目中为这些每一个接口提供一个函数,这些函数的功能非常的相似,只是为了服务于不用的实体.举个例子,假设我们有这些函数. // api/users.js // 创建 export function createUser(u

  • React.memo函数中的参数示例详解

    目录 React.memo?这是个啥? React.memo的第一个参数 父组件 子组件 React.memo优化 React.memo的第二个参数 父组件 子组件 React.memo优化 父组件 子组件 小结 React.memo?这是个啥? 按照官方文档的解释: 如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现.这意味着在这种情况下,React 将跳过渲染组件的操作并直

  • React中前端路由的示例代码

    目录 一. url是什么 二. 使用步骤 一. url是什么 访问不同url, 展示不同的组件 二. 使用步骤 安装React路由:命令行中执行npm install react-router-dom --save(注意此处的版本为npm install react-router-dom@4.3.1 --save) 两个js文件,分别为list.js和newButton.js,要实现访问localhost:3000/button的时候就显示button.js:访问localhost:3000/l

  • React中classnames库使用示例

    目录 classnames的引入 引入 使用 Node.js, Browserify, or webpack: classnames函数的使用 数组的形式 ES6中使用动态类名 结合React一起使用 总结: classnames的引入 从名字上可以看出,这个库是和类名有关的.官方的介绍就是一个简单的支持动态多类名的工具库. 支持使用 npm, Bower, or Yarn 使用 npm安装 npm install classnames 使用 Bower安装 bower install clas

  • 30分钟精通React今年最劲爆的新特性——React Hooks

    你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? --拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function. 你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗? --拥有了Hooks,生命周期钩子函数可以先丢一边了. 你在还在为组件中的this指向而晕头转向吗? --既然Class都丢掉了,哪里还有this?你的人生第一次不再需要面对this. 这样看来,说React Hooks是今年最劲爆的新特性真的毫不夸张.如果你也对react

  • React Hooks的深入理解与使用

    你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? --拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function. 你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗? --拥有了Hooks,生命周期钩子函数可以先丢一边了. 你在还在为组件中的this指向而晕头转向吗? --既然Class都丢掉了,哪里还有this?你的人生第一次不再需要面对this. 这样看来,说React Hooks是今年最劲爆的新特性真的毫不夸张.如果你也对react

随机推荐