首页前端开发JavaScriptreact中常见hook的使用方式

react中常见hook的使用方式

时间2024-02-01 08:10:03发布访客分类JavaScript浏览391
导读:收集整理的这篇文章主要介绍了react中常见hook的使用方式,觉得挺不错的,现在分享给大家,也给大家做个参考。 目录1、什么是hook?2、为什么要出现hook?3、有哪些常用的hoo...
收集整理的这篇文章主要介绍了react中常见hook的使用方式,觉得挺不错的,现在分享给大家,也给大家做个参考。
目录
  • 1、什么是hook?
  • 2、为什么要出现hook?
  • 3、有哪些常用的hook?
    • (1) useState
    • (2) useEffect
    • (3) useContext
    • (4) useRef
    • (5) useReducer
    • (6) useCallback
    • (7) useMemo
    • (8) useImperativeHandle
    • (9) useLayoutEffect
  • 4、如何自定义hook?

    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)=>
    {
     // 使用函数表达式的方式定义了一个函数式组件    returnbutton 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])  returninput 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和绘制到屏幕之间。

    4、如何自定义hook?

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

    以上就是react中常见hook的使用方式的详细内容,更多关于react hook的使用的资料请关注其它相关文章!

    您可能感兴趣的文章:
    • 详解react hooks组件间的传值方式(使用ts)
    • ReactHooks批量更新state及获取路由参数示例解析
    • React之Hooks详解
    • React Hooks使用常见的坑
    • 30分钟带你全面了解React Hooks
    • 详解React Hooks是如何工作的
    • React中10种Hook的使用介绍

    声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

    hookreact

    若转载请注明出处: react中常见hook的使用方式
    本文地址: https://pptw.com/jishu/595142.html
    vue+canvas实现数据实时从上到下刷新瀑布图效果(类似QT的) 关于ListView下隐藏控件的解决方案分享

    游客 回复需填写必要信息