亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

hook如何在react中使用

發布時間:2021-04-08 15:27:42 來源:億速云 閱讀:174 作者:Leah 欄目:開發技術

今天就跟大家聊聊有關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模擬useCallback
const 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中使用有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

唐海县| 普兰店市| 宁阳县| 长岛县| 石屏县| 易门县| 临清市| 盐山县| 米泉市| 岚皋县| 东兴市| 合肥市| 永寿县| 滕州市| 伊通| 宁陵县| 邯郸县| 福鼎市| 克拉玛依市| 兖州市| 连江县| 宣威市| 稻城县| 衡水市| 容城县| 兰西县| 肇东市| 庄河市| 隆林| 岳池县| 吉水县| 兴宁市| 龙海市| 大洼县| 新建县| 巨鹿县| 德昌县| 织金县| 乌审旗| 格尔木市| 正蓝旗|