溫馨提示×

溫馨提示×

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

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

Hook怎么在React中使用

發布時間:2021-04-29 15:54:07 來源:億速云 閱讀:187 作者:Leah 欄目:開發技術

Hook怎么在React中使用?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

1、useState:讓函數式組件擁有狀態

用法示例:

// 計數器
import { useState } from 'react'
const Test = () => {
    const [count, setCount] = useState(0);
    return (
        <>
            <h2>點擊了{count}次</h2>
            <button onClick={() => setCount(count + 1)}>+1</button>
        </>
    );
}
export default Test

PS:class組件中this.setState更新是state是合并, useState中setState是替換。例如:

// 錯誤示例
import { useState } from 'react'
const Test = () => {
    const [counts, setCounts] = useState({
        num1: 0,
        num2: 0
    });
    return (
        <>
            <h2>num1:{counts.num1}</h2>
            <h2>num2:{counts.num2}</h2>
            <button onClick={() => setCounts({ num1: counts.num1 + 1})}>num1+1</button>
            <button onClick={() => setCounts({ num2: counts.num2 + 1})}>num2+1</button>
        </>
    );
}
export default Test

Hook怎么在React中使用

可以看到useState中setState是替換,不會合并,正確更新:

import { useState } from 'react'
const Test = () => {
    const [counts, setCounts] = useState({
        num1: 0,
        num2: 0
    });
    return (
        <>
            <h2>num1:{counts.num1}</h2>
            <h2>num2:{counts.num2}</h2>
            <button onClick={() => setCounts({ ...counts, num1: counts.num1 + 1})}>num1+1</button>
            <button onClick={() => setCounts({ ...counts, num2: counts.num2 + 1})}>num2+1</button>
        </>
    );
}
export default Test

2、useEffect:副作用,取代生命周期

用法示例,在class組件中如果需要在組件掛載后和數據更新后做同一件事,我們會這樣做:

componentDidMount() {
    // 做一些事
}
componentDidUpdate() {
    // 做一些事
}

可以看出來,如果邏輯復雜后,代碼看起來不優雅,且容易造成邏輯混亂,而使用useEffect:

useEffect(() => {
    // 做一些事
});

此刻已經看到了useEffect的基本用法,除此之外,他還可以綁定觸發更新的依賴狀態,默認是狀態中任何數據發生變化副作用都會執行,如:

import { useState, useEffect } from 'react'
const Test = () => {
    const [count1, setCount1] = useState(0);
    const [count2, setCount2] = useState(0);
    useEffect(() => {
        console.log('useEffect觸發了')
    });
    return (
        <>
            <h2>count1:{count1}</h2>
            <h2>count2:{count2}</h2>
            <button onClick={() => setCount1(count1 + 1)}>count1+1</button>
            <button onClick={() => setCount2(count2 + 1)}>count2+1</button>
        </>
    );
}
export default Test

Hook怎么在React中使用

將上述代碼useEffect第二個參數傳入需要綁定的狀態,可綁定多個:

// 語法:useEffect(回調函數,[依賴值])
useEffect(() => {
    console.log('useEffect觸發了')
}, [count1]);

Hook怎么在React中使用

可以看到,只有綁定的count1發生變化才會觸發,如果傳空數組則任何狀態發生變化都不會觸發,此時useEffect的作用就類似class組件中的componentDidMount,所以發送請求通常也會在此執行。

清理副作用

在上面的操作中都不用清理的副作用,然而,有些副作用是需要去清理的,不清理會造成異常甚至內存泄漏,比如開啟定時器,如果不清理,則會多次開啟,從上面可以看到useEffect的第一個參數是一個回調函數,可以在回調函數中再返回一個函數,該函數可以在狀態更新后第一個回調函數執行之前調用,具體實現:

useEffect(() => {
    // 設置副作用
    return () => {
        // 清理副作用
    }
});

3、useContext:跨組件共享數據

React.createContext();創建一個TestContext對象
TestContext.Provider包裹子組件
數據放在<TestContext.Provider value={value}>的value中
子組件中通過useContext(TestContext)獲取值

import React, { useContext, useState } from 'react';
const TestContext = React.createContext();
const Parent = () => {
    const [value, setValue] = useState(0);
    return (
        <div>
            {(() => console.log("Parent-render"))()}
            <button onClick={() => setValue(value + 1)}>value + 1</button>
            <TestContext.Provider value={value}>
                <Child1 />
                <Child2 />
            </TestContext.Provider>
        </div>
    );
}
const Child1 = () => {
    const value = useContext(TestContext);
    return (
        <div>
            {(() => console.log('Child1-render'))()}
            <h4>Child1-value: {value}</h4>
        </div>
    );
}
const Child2 = () => {
    return (
        <div>
            {(() => console.log('Child2-render'))()}
            <h4>Child2</h4>
        </div>
    );
}
export default Parent

Hook怎么在React中使用

至此數據實現共享了,但是可以看到在TestContext中的共享數據只要發生變化,子組件都會重新渲染,Child2并沒有綁定數據,不希望他做無意義的渲染,可以使用React.memo解決,實現:

const Child2 = React.memo(() => {
    return (
        <div>
            {(() => console.log('Child2-render'))()}
            <h4>Child2</h4>
        </div>
    );
});

Hook怎么在React中使用

4、useCallback:性能優化

語法:

// useCallback(回調函數,[依賴值])
const handleClick = useCallback(()=> {
    // 做一些事
}, [value]);

useCallback返回的是一個 memoized(緩存)函數,在依賴不變的情況下,多次定義的時候,返回的值是相同的,他的實現原理是當使用一組參數初次調用函數時,會緩存參數和計算結果,當再次使用相同的參數調用該函數時,會直接返回相應的緩存結果。

優化性能例子:

import React, { useState, useCallback, memo } from 'react';
const Parent = () => {
    const [value1, setValue1] = useState(0);
    const [value2, setValue2] = useState(0);
    const handleClick1 = useCallback(()=> {
        setValue1(value1 + 1);
    }, [value1]);
    const handleClick2 = useCallback(()=> {
        setValue2(value2 + 1);
    }, [value2]);
    return (
        <>
            {(() => console.log("Parent-render"))()}
            <h4>{value1}</h4>
            <h4>{value2}</h4>
            <Child1 handleClick1={handleClick1} />
            <Child2 handleClick2={handleClick2} />
        </>
    );
}
const Child1 = memo(props => {
    return (
        <div>
            {(() => console.log("Child1-render"))()}
            <button onClick={() => props.handleClick1()}>value1 + 1</button>
        </div>
    );
});
const Child2 = memo(props => {
    return (
        <div>
            {(() => console.log("Child2-render"))()}
            <button onClick={() => props.handleClick2()}>value2 + 1</button>
        </div>
    );
});
export default Parent

Hook怎么在React中使用

useCallback返回的是一個memoized回調函數,僅在其中綁定的一個依賴項變化后才更改可防止不必要的渲染,在跨組件共享數據中舉例的事件是在父組件中點擊觸發,而現在是使用狀態提升,在父組件中傳遞方法供子組件調用,每次render時函數也會變化,導致子組件重新渲染,上面例子useCallback將函數進行包裹,依賴值未發生變化時會返回緩存的函數,配合React.memo即可優化無意義的渲染。

5、useMemo:性能優化

語法:

// useMemo(回調函數,[依賴值])
useMemo(() => {
    // 做一些事情
},[value]);

先看一個例子:

import React, { useState } from 'react'
const Test = ()=> {
    const [value, setValue] = useState(0);
    const [count, setCount] = useState(1);
    const getDoubleCount = () => {
        console.log('getDoubleCount進行計算了');
        return count * 2;
    };
    return (
        <div>
            <h3>value: {value}</h3>
            <h3>doubleCount: {getDoubleCount()}</h3>
            <button onClick={() => setValue(value + 1)}>value+1</button>
        </div>
    )
}
export default Test

Hook怎么在React中使用

可以看到getDoubleCount依賴的是count,但value發生變化它也重新進行了計算渲染,現在只需要將getDoubleCount使用useMemo進行包裹,如下:

import React, { useState, useMemo } from 'react'
const Test = ()=> {
    const [value, setValue] = useState(0);
    const [count, setCount] = useState(1);
    const getDoubleCount = useMemo(() => {
        console.log('getDoubleCount進行計算了');
        return count * 2;
    },[count]);
    return (
        <div>
            <h3>value: {value}</h3>
            <h3>doubleCount: {getDoubleCount}</h3>
            <button onClick={() => setValue(value + 1)}>value+1</button>
        </div>
    )
}
export default Test

Hook怎么在React中使用

現在getDoubleCount只有依賴的count發生變化時才會重新計算渲染。

useMemo和useCallback的共同點:

  • 接收的參數都是一樣的,第一個是回調函數,第二個是依賴的數據

  • 它們都是當依賴的數據發生變化時才會重新計算結果,起到了緩存作用

useMemo和useCallback的區別:

  • useMemo計算結果是return回來的值,通常用于緩存計算結果的值

  • useCallback計算結果是一個函數,通常用于緩存函數

6、useRef用法:例如要實現點擊button按鈕使input輸入框獲得焦點:

import React, { useState, useMemo } from 'react'
const Test = ()=> {
    const [value, setValue] = useState(0);
    const [count, setCount] = useState(1);
    const getDoubleCount = useMemo(() => {
        console.log('getDoubleCount進行計算了');
        return count * 2;
    },[count]);
    return (
        <div>
            <h3>value: {value}</h3>
            <h3>doubleCount: {getDoubleCount}</h3>
            <button onClick={() => setValue(value + 1)}>value+1</button>
        </div>
    )
}
export default Test

這樣看起來非常像React.createRef(),將上面代碼中的useRef()改成React.createRef()也能實現同樣的效果,那為什么要設計一個新的hook?難道只是會了加上use,統一hook規范?
事實上,它們確實不一樣。

官網的說明如下:

useRef returns a mutable ref object whose .current property is initialized to the passed
argument (initialValue). The returned object will persist for the full lifetime of the component.

翻譯:

Hook怎么在React中使用

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

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

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女