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内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

React Hooks钩子中API的使用示例分析的更多相关文章

  1. HTML5之消息通知的使用(Web Notification)

    通知可以说是web中比较常见且重要的功能,私信、在线提问、或者一些在线即时通讯工具我们总是希望第一时间知道对方有了新的反馈。本篇文章主要介绍了HTML5之消息通知的使用(Web Notification),感兴趣的小伙伴们可以参考一下

  2. ios – React native链接到另一个应用程序

    如果是错误的,有人知道如何调用正确的吗?

  3. ios – 我可以使用哪些iPhone OS API来实现类似于iBook页面翻转过渡的过渡动画?

    >UIKitAPI中的某个地方是否可以使用该动画,还是我必须自己实现?它肯定有3D感觉,他们可以使用OpenGLESAPI吗?解决方法Apple当然使用OpenGLES来实现它.Apple使用的实际API是私有的,但thisblogger具有示例代码的实现的开始.

  4. iOS 7,用于断开调用的私有API CTCallDisconnect不起作用

    谢谢!

  5. 我应该使用哪个高级API来管理iOS上的UDP套接字?

    在“NetworkProgrammingTopicsConceptualGuide”的“UsingSocketsandStreams”一章中,Apple说:Note:POSIXnetworkingdoesnotactivatethecellularradiooniOS.Forthisreason,thePOSIXnetworkingAPIisgenerallydiscouragediniOS.同样

  6. 保护MY REST API仅用于MY IOS APP

    我在Laravel中设计一个RESTAPI,用于我的ios应用程序.目前我被困在以下几点:如何保护我的RESTAPI只允许访问我的ios应用程序?听起来我需要通过向我的IOSAPP授予一个私钥来将类似于HMAC方法的内容合并到我的IOSAPP代码中.当从iosapp中运行请求时,我传递带有私钥和其他数据的哈希,然后当在服务器上收到请求时,我通过重新计算哈希来检测请求是否来自应用程序内的用户.我不知道这是否安全&我会认为不是吗?

  7. ios – 尝试向我们分配IP而不是localhost或home时,NSURLSession失败

    我有一台本地运行的服务器(我的IP是192.168.0.98),并且已经尝试使用一些网络代码来访问它.最初这是通过AFNetworking完成的,但我现在用这样的NSURLSession完成了它:然后我用这3个URL运行它:>http://localhost:8080/api–>作品.>http://127.0.0.1:8080/api–>作品.>http://192.168.0.98:8080/

  8. ios – React Native – 在异步操作后导航

    我正在使用ReactNative和Redux开发移动应用程序,我正面临着软件设计问题.我想调用RESTAPI进行登录,如果该操作成功,则导航到主视图.我正在使用redux和thunk所以我已经实现了异步操作,所以我的主要疑问是:我应该把逻辑导航到主视图?我可以直接从动作访问导航器对象并在那里执行导航吗?.我对组件中的逻辑没有信心.似乎不是一个好习惯.有没有其他方法可以做到这一点?

  9. 适用于iOS的Google云端硬盘实时API

    我想使用GoogleDrive和新的实时API在我的iOS应用中实现实时协作.我知道我可以在Objective-C中设置一个Web视图,并在Web视图和我的本机应用程序之间建立双向通信,因此使用javascript库,但我担心这对于高容量来说效率低下数据流量.我希望可能会有一个原生的解决方案即将出现.有关Objective-C的GoogleApi客户端库是否会更新以包含Google云端硬盘实时API的任何消息?

  10. ios – 如何通过iPhone中的Graph API在Facebook上“喜欢”和“评论”?

    我正在使用图形api显示新闻源.我对以下问题有疑问.>我想为每个新闻提要帖子提供“赞”功能.>我想为每个新闻提要帖子提供“评论”功能.有人可以帮助我如何使用iPhone中的图形API来解决这个问题.解决方法请参考我的答案:HowtocommentorlikeaphotoinfacebookthroughFBconnectorGraphAPIiniPhoneSDK?只需将您的访问令牌发送到https

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部