最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React中useState和useEffect的用法詳解

 更新時(shí)間:2023年06月16日 09:46:59   作者:何遇er  
Hooks?發(fā)布之后,函數(shù)組件能擁有自己的?state,React提供了很多內(nèi)置的Hooks,這篇文章就來和大家介紹一下useState?和?useEffect的使用,需要的可以參考一下

之前在不討論 React Hooks 和組件生命周期的基礎(chǔ)上介紹了函數(shù)組件和類組件的差別,現(xiàn)在介紹一個(gè)為函數(shù)組件而生的知識(shí)點(diǎn),即:React Hooks。Hooks 是函數(shù),在 React 16.8 正式發(fā)布,它對(duì)類組件沒有影響。

類組件的功能強(qiáng)大,能擁有自己的state,有生命周期,開發(fā)人員能根據(jù)需求在特定的生命周期中執(zhí)行自己要想的操作,如:發(fā)送Ajax請(qǐng)求等。類組件功能雖強(qiáng),但它存在如下問題:

1.必須時(shí)常關(guān)注 this 關(guān)鍵字的指向,這對(duì)初學(xué)者而言不是一件容易的事。

2.相同的生命周期函數(shù)在類組件中最多定義一個(gè),這導(dǎo)致彼此無關(guān)的邏輯代碼被揉雜在同一生命周期函數(shù)中。

3.不同的生命周期函數(shù)可能包含相同的代碼,最常見便是 componentDidMount 和 componentDidUpdate。

Hooks 發(fā)布之后,函數(shù)組件能擁有自己的 state,也能感知到組件被銷毀和 DOM 被繪制到屏幕上的時(shí)機(jī),但是沒有類組件存在的那三個(gè)問題。React提供了很多內(nèi)置的Hooks,在本文介紹 useState 和 useEffect。

useState

它是一個(gè)與狀態(tài)管理相關(guān)的hook,它讓函數(shù)組件擁有狀態(tài),是最常用的Hooks之一,類型定義如下:

function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];

從類型定義可以看出,useState 有兩個(gè)重載,分別是傳參數(shù)和不傳參數(shù),不論是否傳參數(shù),useState 都返回一個(gè)長(zhǎng)度為 2 的數(shù)組,數(shù)組的第一個(gè)位置是狀態(tài),它可以是任何數(shù)據(jù)類型,類型參數(shù) S 用于注釋它的類型,第二個(gè)位置是一個(gè)用于更新狀態(tài)的函數(shù),為了語(yǔ)言上的便利本小節(jié)將該函數(shù)記為 setState。接下來,介紹 useState 的基本用法。

當(dāng) useState 的參數(shù)不是函數(shù)

此時(shí),useState 的參數(shù)作為狀態(tài)的初始值,如果沒有傳參數(shù),那么狀態(tài)的初始值為 undefined。用法如下:

import React, { useState } from 'react'
export function UseStateWithoutFunc() {
    const [name, setName] = useState<string>('何遇')
    const [age, setAge] = useState<number>()
    function onChange() {
        setName(Math.random() + '') // 修改name
        setAge(Math.random()) // 修改age
    }
    return (
        <>
        <div>姓名: {name}</div>
        <div>年齡: {age === undefined ? '未知' : age}</div>
        <button onClick={onChange}>click</button>
        </>
    )
}

UseStateWithoutFunc 組件有 name 和 age 這兩個(gè)狀態(tài),name 只能是 string 類型,初始值為'何遇',age 的數(shù)據(jù)類型是 number 或 undefined,初始值為undefined。

當(dāng) useState 的參數(shù)是函數(shù)

此時(shí),函數(shù)的返回值是狀態(tài)的初始值。某些時(shí)候,狀態(tài)的初始值要經(jīng)過計(jì)算才能得到,此時(shí)推薦將函數(shù)作為 useState 的參數(shù),該函數(shù)只在組件初始渲染執(zhí)行一次。用法如下:

function UseStateWithFunc() {
    const [count, setCount] = useState<number>(() => {
        // 這個(gè)函數(shù)只在初始渲染的時(shí)候執(zhí)行,后續(xù)的重新渲染不再執(zhí)行
        return Number(localStorage.getItem('count')) || 0
    })
    function onChange() {/** todo*/}
    return (
        <>
        <div>count: {count}</div>
        <button onClick={onChange}>click</button>
        </>
    )
}

上述 useState 的參數(shù)是函數(shù),count 的初始值為該函數(shù)的返回值,數(shù)據(jù)類型是 number。

修改狀態(tài)的值

延用上述代碼中的 setCount,修改狀態(tài)有兩種方式。用法如下:

// 用法一
setCount((count) => {
   return count + 1
})
// 用法二
setCount(0)

如果 setCount 的參數(shù)是函數(shù),那么 count 現(xiàn)在的值將以參數(shù)的形式傳給該函數(shù),函數(shù)的返回值用于更新狀態(tài)。如果 setCount 的參數(shù)不是函數(shù),那么該參數(shù)將用于更新狀態(tài)。修改狀態(tài)只能使用與它相關(guān)的 setState ,且必須滿足 Immutability 原則,狀態(tài)值發(fā)生變更將導(dǎo)致組件重新渲染,重新渲染時(shí),useState 返回的第一個(gè)值始終是狀態(tài)最新的值,不會(huì)重置為初始值。

目前已介紹完 useState 的基本用法,觀察下面這段更復(fù)雜的代碼,分析瀏覽器打印的結(jié)果。

function UseStateAdvanceDemo() {
    // count 的初始值為 0
    const [count, setCount] = useState<number>(0)
    const onClick = () => {
        setCount((prevCount) => prevCount + 1) // 將count在原來的基礎(chǔ)上加1
        setTimeout(() => {
            console.log(count) // 分析瀏覽器打印的結(jié)果
        }, 1000)
    }
    return <button onClick={onClick}>打開開發(fā)者工具再點(diǎn)擊</button>
}

如果你理解了React 的函數(shù)組件中介紹的知識(shí),那么能輕而易舉的分析出瀏覽器打印的值為0而不是1。再?gòu)?qiáng)調(diào)一次,在函數(shù)組件中取 state 和 props 拿到的都是本次渲染的值,在本次渲染范圍內(nèi),props 和 state 始終不變。在上述代碼中,調(diào)用 setCount 會(huì)導(dǎo)致組件重新渲染,在下一次渲染時(shí) count 的值為 1,但 console.log(count) 打印的是本次渲染時(shí) count 的值,所以結(jié)果為 0。

useEffect

useEffect 是除 useState 之外另一個(gè)常用的 Hook,它比 useState 的理解難度更大,但只要你明白函數(shù)組件每次渲染都有它自己的 state 和 props,那么理解useEffect 將變得容易。使用 useEffect 能讓開發(fā)人員知道 DOM 什么時(shí)候被繪制到了屏幕,組件什么時(shí)候被銷毀了,有些開發(fā)人員認(rèn)為它是類組件 componentDidMount、componentDidUpdate 和 componentWillUnmount 生命周期函數(shù)的結(jié)合,但實(shí)際上函數(shù)組件沒有與類組件類似的生命周期概念。

useEffect 類型定義如下:

type EffectCallback = () => (void | Destructor);
function useEffect(effect: EffectCallback, deps?: DependencyList): void;

從類型定義可以看出,useEffect 最多接受兩個(gè)參數(shù),第一個(gè)參數(shù)是函數(shù),可以有返回值,之后將該函數(shù)稱為 effect;第二個(gè)參數(shù)非必填,是個(gè)數(shù)組,它是 effect 的依賴,稱為 deps。deps 用于確定 effect 在本次渲染是否執(zhí)行,如果執(zhí)行,那么在瀏覽器將 DOM 繪制到屏幕之后執(zhí)行,可以將 Ajax 請(qǐng)求,訪問 DOM 等操作放在effect 中,它不會(huì)阻塞瀏覽器繪制。函數(shù)組件可以多次使用 useEffect,每使用一次就定義一個(gè) effect,這些 effect 的執(zhí)行順序與它們被定義的順序一致,建議將不同職責(zé)的代碼放在不同的 effect 中。接下來從 effect 的清理工作和它的依賴這兩個(gè)方面介紹 useEffect。

effect沒有清理工作

effect 沒有清理工作就意味著它沒有返回值,代碼如下:

function EffectWithoutCleanUp() {
    const [name, setTitle] = useState<string>('何遇')
    useEffect(() => {
        document.title = name
    })
    return (
      	// something
    )
}

上述代碼定義了一個(gè) effect,它的作用是將 document.title 設(shè)置成本次渲染時(shí) name 的值。

effect 有清理工作

effect 的清理工作指 effect 返回的函數(shù),該函數(shù)在組件重新渲染后和組件卸載時(shí)被調(diào)用,下面的代碼定義了一個(gè)有清理工作的 effect。

function EffectWithCleanUp() {
    const [name, setTitle] = useState<string>('何遇')
    useEffect(() => {
        const onBodyClick = () => {/** todo */}
        document.body.addEventListener('click', onBodyClick)
        // 在返回的函數(shù)中定義與該effect相關(guān)的清理工作
        return () => {
            document.body.removeEventListener('click', onBodyClick)
        }
    })
    return (
        // something
    )
}

上述 effect 在 DOM 被繪制到界面之后給 body 元素綁定 click 事件,組件重新渲染之后將上一次 effect 綁定的 click 事件解綁。該 effect 在組件首次渲染和之后的每次重新渲染都將執(zhí)行,如果組件的狀態(tài)更新頻繁,那么組件重新渲染也會(huì)很頻繁,這導(dǎo)致 body 頻繁綁定 click 事件又解綁 click事件。是否有辦法使組件只在首次渲染時(shí)給 body 綁定事件呢?當(dāng)然有。

effect 的依賴

前面兩個(gè)示例定義的 effect 沒有指明依賴,因此組件每一輪渲染都會(huì)執(zhí)行它們。下面的代碼讓組件只在首次渲染時(shí)給 body 綁定事件,代碼如下:

useEffect(() => {
        const onBody = () => {/** todo */}
        document.body.addEventListener('click', onBody)
        return () => {
            // 在組件卸載時(shí)將事件解綁
            document.body.removeEventListener('click', onBody)
        }
}, [])

給 useEffect 第二個(gè)參數(shù)傳空數(shù)據(jù)意味著 effect 沒有依賴,該 effect 只在組件初始渲染時(shí)執(zhí)行,它的清理工作在組件卸載時(shí)執(zhí)行。對(duì)于綁定 DOM 事件而言這是一件好事,它可以防止事件反復(fù)綁定和解綁,但問題是,如果在事件處理程序中訪問組件的 state 和 props,那么只能拿到它們的初始值,拿不到最新的值。是否有辦法讓 effect 始終拿到 state 和 props 最新的值呢?有。

給 effect 傳遞依賴項(xiàng),React 會(huì)將本次渲染時(shí)依賴項(xiàng)的值與上一次渲染時(shí)的值進(jìn)行淺對(duì)比,如果結(jié)論是它們其中之一有變化,那么該 effect 會(huì)被執(zhí)行,否則不會(huì)執(zhí)行。為了讓 effect 拿到它所需 state 和 props 的最新值,effect 中所有要訪問的外部變量都應(yīng)該作為依賴項(xiàng)放在 useEffect 第二個(gè)參數(shù)中。代碼如下:

useEffect(() => {
       const onBody = () => {
       console.log(name) // 始終得到最新的name值
    }
        document.body.addEventListener('click', onBody)
        return () => {
            document.body.removeEventListener('click', onBody)
        }
}, [name])

上述 effect 在組件初始渲染會(huì)執(zhí)行,當(dāng) name 發(fā)生變化導(dǎo)致組件重新渲染也會(huì)執(zhí)行,相應(yīng)的,組件卸載時(shí)和由 name 變化導(dǎo)致組件渲染之后將清理上一個(gè) effect。

提示:函數(shù)組件每次渲染時(shí),effect 都是一個(gè)不同的函數(shù),在函數(shù)組件內(nèi)的每一個(gè)位置(包括事件處理函數(shù),effects,定時(shí)器等等)只能拿到定義它們的那次渲染的 props 和 state。

函數(shù)組件生命周期內(nèi) hooks 的調(diào)用順序如下圖

以上就是React中useState和useEffect的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于React useState useEffect的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • react實(shí)現(xiàn)導(dǎo)航欄二級(jí)聯(lián)動(dòng)

    react實(shí)現(xiàn)導(dǎo)航欄二級(jí)聯(lián)動(dòng)

    這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)導(dǎo)航欄二級(jí)聯(lián)動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • React過渡動(dòng)畫組件基礎(chǔ)使用介紹

    React過渡動(dòng)畫組件基礎(chǔ)使用介紹

    在開發(fā)中,我們想要給一個(gè)組件的顯示和消失添加某種過渡動(dòng)畫,可以很好的增加用戶體驗(yàn)。 當(dāng)然,我們可以通過原生的CSS來實(shí)現(xiàn)這些過渡動(dòng)畫,這篇文章主要介紹了React過渡動(dòng)畫組件使用
    2022-09-09
  • react中hooks使用useState的更新不觸發(fā)dom更新問題及解決

    react中hooks使用useState的更新不觸發(fā)dom更新問題及解決

    這篇文章主要介紹了react中hooks使用useState的更新不觸發(fā)dom更新問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • react-router v4如何使用history控制路由跳轉(zhuǎn)詳解

    react-router v4如何使用history控制路由跳轉(zhuǎn)詳解

    這篇文章主要給大家介紹了關(guān)于react-router v4如何使用history控制路由跳轉(zhuǎn)的相關(guān)資料,文中通過示例代碼介紹的的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • React?SSR架構(gòu)Stream?Rendering與Suspense?for?Data?Fetching

    React?SSR架構(gòu)Stream?Rendering與Suspense?for?Data?Fetching

    這篇文章主要為大家介紹了React?SSR架構(gòu)Stream?Rendering與Suspense?for?Data?Fetching解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 關(guān)于react-router的幾種配置方式詳解

    關(guān)于react-router的幾種配置方式詳解

    本篇文章主要介紹了關(guān)于react-router的幾種配置方式詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • React實(shí)現(xiàn)點(diǎn)擊切換組件效果

    React實(shí)現(xiàn)點(diǎn)擊切換組件效果

    這篇文章主要為大家詳細(xì)介紹了如何基于React實(shí)現(xiàn)點(diǎn)擊切換組件效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以學(xué)習(xí)一下
    2023-08-08
  • react系列從零開始_簡(jiǎn)單談?wù)剅eact

    react系列從零開始_簡(jiǎn)單談?wù)剅eact

    下面小編就為大家?guī)硪黄猺eact系列從零開始_簡(jiǎn)單談?wù)剅eact。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • react后臺(tái)系統(tǒng)最佳實(shí)踐示例詳解

    react后臺(tái)系統(tǒng)最佳實(shí)踐示例詳解

    這篇文章主要為大家介紹了react后臺(tái)系統(tǒng)最佳實(shí)踐示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • React 中引入 CSS 高階用法的方案詳解

    React 中引入 CSS 高階用法的方案詳解

    這篇文章主要介紹了React中引入CSS高階用法的方案詳解,至于使用react用哪種方案引入css,并沒有一個(gè)絕對(duì)的答案,可以根據(jù)各自情況選擇合適的方案,需要的朋友可以參考下
    2024-02-02

最新評(píng)論

彭山县| 锡林郭勒盟| 荣昌县| 武义县| 安阳市| 和田市| 三明市| 定安县| 凌云县| 定西市| 潮安县| 于田县| 屯门区| 扬中市| 云龙县| 都江堰市| 锡林郭勒盟| 平南县| 潼关县| 抚顺县| 长治县| 西吉县| 巴楚县| 来凤县| 石棉县| 大丰市| 清河县| 保山市| 萝北县| 云南省| 宜宾县| 华蓥市| 友谊县| 加查县| 泰州市| 邢台市| 怀集县| 虹口区| 洪湖市| 石柱| 贵州省|