文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

hook如何在react中使用

2023-06-14 10:30

关注

今天就跟大家聊聊有关hook如何在react中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1、什么是hook?

react hook是react 16.8推出的方法,能够让函数式组件像类式组件一样拥有state、ref、生命周期等属性。

2、为什么要出现hook?

函数式组件是全局当中一个普通函数,在非严格模式下this指向window,但是react内部开启了严格模式,此时this指向undefined,无法像类式组件一样使用state、ref,函数式组件定义的变量都是局部的,当组件进行更新时会重新定义,也无法存储,所以在hook出现之前,函数式组件有很大的局限性,通常情况下都会使用类式组件来进行代码的编写。

3、有哪些常用的hook?

(1) useState

使函数式组件也能保存状态的一个hook,这个hook的入参是状态的初始值,返回值是一个数组,数组里第一个参数为状态的值,第二个参数为修改状态的方法。

// 初始化const [ count,  setCount ] = useState(0)// 更新setCount(count+1)

(2) useEffect

函数式组件用来模拟生命周期的hook,可以模拟组件挂载完成、更新完成、即将卸载三个阶段,即componentDidMount、componentDidUpdate、componentWillUnmount。

useEffect的一个参数为函数,表示组件挂载、更新时执行的内容,在函数里再返回一个函数,表示组件即将卸载时调用的函数。

第二个参数为可选项,可传入数组,数组里可以为空,表示不依赖任何状态的变化,即只在组件即将挂载时执行,后续任何状态发生了变化,都不调用此hook。数组里也可以定义一或多个状态,表示每次该状态变化时,都会执行此hook。

useEffect(()=>{  // 这样模拟的是 componentDidMount}, [])useEffect(()=>{  // 这样模拟的是componentDidMount 以及当count发生变化时执行componentDidUpdate}, [count])useEffect(()=>{  return ()=>{  // 这样模拟的是 componentWillUnmount  }}, [])

(3) useContext

在没有hook之前,我们通常都会通过 xxxContext.Provider 和 xxxContext.Consumer 的方式来传递和获取context的值,使用hook之后,传递context的方式不变,但子元素获取context的方式变得更加的简洁。

// 以前的定义方式const CountContext = React.createContext() <CountContext.Provider value={{ count: 10 }}>     <...自定义的组件> </CountContext.Provider>// 子元素<CountContext.Consumer>    { value => { console.log(value.count) }} //10</CountContext.Consumer>//使用context的获取方式const countObj = useContext(CountContext)console.log(countObj.count) // 10

(4) useRef

useRef和类式组件中createRef用法比较类似,返回一个ref对象,这个对象在函数的整个生命周期都不变,根据这个特性,有两种比较常见的用法。

① 用于dom元素或者组件上,通过current属性可以获取到dom元素或者类式组件的实例对象。需要注意的是,无论是useRef还是createRef或者是回调形式、字符串形式的ref,都是不能直接给函数式组件定义的,因为函数式组件的this指向undefined,没有实例对象,只能通过forwardRef定义到函数式组件中的某个dom元素。

// 这样就将传递给函数式组件的ref绑定在了函数式组件内部的input标签上import React, { useRef, forwardRef } from 'react'// 使用函数表达式的方式定义了一个函数式组件const InputCom = forwardRef((props, ref) => {    return <input ref={ref}/> })export default function refDemo(){    const comRef = useRef()    return(<div>       <InputCom ref={comRef}/>         </div>)  }

② 保存一个数据,该数据如果不手动修改,它在整个生命周期中都不变

const [ count, setCount ] = useState(0)const prevCount = useState(count)// 当count发生变化时,组件更新,对count的前一次数据进行保存useEffect(()=>{  prevCount.current = count}, [count])

(5) useReducer

useReducer相当于是useState的升级版,作用与useState类似,都是用来保存状态,但它的不同点在于可以定义一个reducer的纯函数,来处理复杂数据。

// 定义一个处理数据的reducer纯函数function reducer(prevState, action){  switch(action.type){    case 'increment':      return {...prevState, count: prevState.count + 1 }    case 'decrement':      return {...prevState, count: prevState.count - 1 }    default:      return prevState  }}// 初始化状态const [ count, dispatch ] = useReducer(reducer, { count: 0 })// 修改状态,此时的修改需要派发一个action,让传入的reducer函数进行处理dispatch({ type: 'increment' })

(6) useCallback

函数式组件中,每一次更新状态,自定义的函数都要进行重新的声明和定义,如果函数作为props传递给子组件,会造成子组件不必要的重新渲染,有时候子组件并没有使用到父组件发生变化的状态,此时可以使用useCallback来进行性能优化,它会为函数返回一个记忆的值,如果依赖的状态没有发生变化,那么则不会重新创建该函数,也就不会造成子组件不必要的重新渲染。

import React, { useState, useCallback, memo } from 'react'const AddBtn = memo((props)=>{ // 使用函数表达式的方式定义了一个函数式组件    return<button onClick={props.increment}>+1</button>})export default function CallBackPerformance(){    const [ count, setCount ] = useState(0)    const [ show, setShow ] = useState(true)    const increment1 = () => {        console.log('increment1被调用了')        setCount(count+1)    }   const increment2 = useCallback(()=>{  // 使用了useCallback来优化的函数         console.log('increment2被调用了')         setCount(count+1)    },[count])    return(<div>            <div>当前计数:{count}</div>            <AddBtn increment={increment1} name="1"/>            <AddBtn increment={increment2} name="2"/>            <button onClick={e => setShow(!show)}>切换show</button>        </div>)}// 当show这个状态发生变化时,子组件increment1会重新渲染,increment2不会重新渲染

(7) useMemo

useMemo也是返回一个记忆的值,如果依赖的内容没有发生改变的话,这个值也不会发生变化,useMemo与useCallback的不同点在于useMemo需要在传入的函数里需要return 一个值,这个值可以是对象、函数,格式如下。

useMemo(()=>{   return { count }}, [count])// 使用useCallback时   const increment2 = useCallback(()=>{    setCount(count+1)},[count])// 使用useMemo模拟useCallbackconst increment2 = useCallback(()=>{    return ()=>{        setCount(count+1)    }},[count])// useMemo的应用场景,当要进行一些复杂的计算时,//计算的值没有发生变化,并不需要每一次更新都重新计算import React, { useState, useMemo } from 'react'const calculateNum = (count) => {    console.log('total重新计算了')    let total = 0    for(let i = 0; i <= count; i++){        total += i    }    return total}export default function ComplexUseMemo(){    const [ count, setCount ] = useState(10)    const [ show, setShow ] = useState(true)    const total = useMemo(()=>{        return calculateNum(count)    }, [count])    return(<div>        <div>{total}</div>        <button onClick={e=>setCount(count+1)}>+1</button>        <button onClick={e=>setShow(!show)}>切换show</button>    </div>)}

(8) useImperativeHandle

这个是与forwardRef配合来使用的,当我们对函数式组件使用forwardRef将ref指定了dom元素之后,那就父组件就可以任意的操作指定的dom元素,使用useImperativeHandle就是为了控制这样的一种行为,指定父元素可操作的子元素的方法。

import React, {  useRef, useImperativeHandle, forwardRef } from 'react'const InputComp = forwardRef((props, ref)=>{  const childInputRef = useRef()  useImperativeHandle(ref, ()=>({    focus: ()=>{      childInputRef.current.focus()    }  }), [childInputRef.current])  return<input ref={childInputRef}></input>})export default function ImperativeHookDemo() {  const inputRef = useRef()  return(<div>      <InputComp ref={inputRef}/>      <button onClick={e=>inputRef.current.focus()}>聚焦</button>    </div>)}

(9) useLayoutEffect

这个方法与useEffect类似,只是执行的顺序稍有不同,useEffect是在组件渲染绘制到屏幕上之后,useLayoutEffect是render和绘制到屏幕之间。

hook如何在react中使用

4、如何自定义hook?

hook只能定义在函数式组件中,不能在普通函数中使用,如果我们想要使用到上面的hook来封装一些方法供很多个组件调用,这时候就需要自定义hook,自定义hook的命名就是在函数名前加 use,函数名由 saveInfo 改为 useSaveInfo 即可。

看完上述内容,你们对hook如何在react中使用有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网行业资讯频道,感谢大家的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯