react hooks(useState、useEffect、useRef詳解)


好巧不巧,工作了一年跳槽了,之前用的vue,現在用的react~ 嗯!工作使人進步!現在開始學react吧!

切入正題~

react hooks是React16.8.0之后出現的,

類組件存在的問題:

  • this指向問題
  • 生命周期繁瑣
  • 創建類的實例開銷較大

而函數組件函數組件沒有this,沒有生命周期,沒有狀態state,函數的執行開銷比創建類實例的開銷要小。

因此,為了提高性能,盡量使用函數組件。

然而函數組件有個最大的問題就是沒有狀態state,所以react官方出了個hooks來解決這個問題。

項目中最常用的幾個hook:

useState

1. useState最好寫到函數的起始位置,便於閱讀
2. useState嚴禁出現在代碼塊(判斷、循環)中
3. useState返回的函數(數組的第二項),引用不變(節約內存空間)
4. 使用函數改變數據,若數據和之前的數據完全相等(使用Object.is比較),不會導致重新渲染,以達到優化效率的目的。
5. 使用函數改變數據,若傳入的是值,只會保留最后一次的函數執行,若傳入的是函數,會在事件完成后統一執行。
import React, { useState } from 'react';// 引入state hook


export default function App() {
    console.log("App render")
    const [n, setN] = useState(0); //使用一個狀態,該狀態的默認值是0
    return <div>
        <button onClick={() => {
            setN(n - 1);
            setN(n - 2);// 傳入值,只會保留最后一次setN的執行
            // setN(prevN => prevN - 1); 
            // setN(prevN => prevN - 1);//傳入函數,在事件完成之后統一執行
        }}>-</button>
        <span>{n}</span>
    </div>
}
6. 如果要實現強制刷新組件
  • 類組件:使用forceUpdate函數
  • 函數組件:使用一個空對象的useState

類組件

import React, { Component } from 'react'

export default class App extends Component {
    render() {
        return (
            <div>
                <button onClick={()=>{
                    //不會運行shouldComponentUpdate
                    this.forceUpdate();//強制重新渲染
                }}>強制刷新</button>
            </div>
        )
    }
}

函數組件

import React, { useState } from 'react'

export default function App() {

const [, forceUpdate] = useState({}); return <div> <p > <button onClick={() => { forceUpdate({}); }}>強制刷新</button> </p> </div> }

 

useEffect

它能在函數組件中執行副作用,並且它與 class 中的生命周期函數極為類似。

副作用:

1. ajax請求
2. 計時器
3. 其他異步操作
4. 更改真實DOM對象
5. 本地存儲
6. 其他會對外部產生影響的操作
 
  • 副作用函數的運行時間點,是在頁面完成真實的UI渲染之后。因此它的執行是異步的,並且不會阻塞瀏覽器
與類組件中componentDidMount和componentDidUpdate的區別
componentDidMount和componentDidUpdate,更改了真實DOM,但是用戶還沒有看到UI更新,是同步的。
useEffect中的副作用函數,更改了真實DOM,並且用戶已經看到了UI更新,是異步的。
  • 每個函數組件中,可以多次使用useEffect,但不要放入判斷或循環等代碼塊中。
  • useEffect中的副作用函數,可以有返回值,返回值必須是一個函數,該函數叫做清理函數
在每次運行副作用函數之前,運行返回的函數
首次渲染組件不會運行
組件被銷毀時一定會運行
  • useEffect函數,可以傳遞第二個參數
第二個參數是一個數組
數組中記錄該副作用的依賴數據
當組件重新渲染后,只有依賴數據與上一次不一樣時,才會執行副作用
所以,當傳遞了依賴數據之后,如果數據沒有發生變化
副作用函數僅在第一次渲染后運行,清理函數僅在卸載組件后運行
 
import React, { useState, useEffect } from 'react'

function Test() {
    useEffect(() => {
        console.log("副作用函數,僅掛載時運行一次")
        return () => {
            console.log("清理函數,僅卸載時運行一次")
        };
    }, []); //使用空數組作為依賴項,則副作用函數僅在掛載的時候運行
    console.log("渲染組件");
    const [, forceUpdate] = useState({})

    return <h1>Test組件 <button onClick={() => {
        forceUpdate({})
    }}>刷新組件</button></h1>
}

export default function App() {
    const [visible, setVisible] = useState(true)
    return (
        <div>
            {
                visible && <Test />
            }
            <button onClick={() => {
                setVisible(!visible);
            }}>顯示/隱藏</button>

        </div>
    )
}

 

useRef

useRef(value)返回一個對象:{current: value}

  • 在每次渲染時返回同一個 ref 對象
  • 變更 .current 屬性不會引發組件重新渲染
import React, { useRef } from 'react'
export default function App() {
    console.log('app render')
    const nRef = useRef(10); // {current:10}
    return (
        <div>
            <h1>{nRef.current}不會變</h1>
            <button onClick={() => {nRef.current--;console.log(nRef.current, 'nRef.current變化')}}>減少</button>
        </div>
    )
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM