【React hooks】關於useCallback帶來的閉包問題實踐方案


問題描述

// 舉個栗子,我用hooks 寫了這么一個組件
let Test = () => {
    /** Search base infos */
    const [searchID, setSearchID] = useState(0)

    /** Search info action */
    const onSearchInfos = useCallback(() => {
        let fetchUrl = '/api/getSearchInfos'
        let fetchParams = { searchID }
        fetch(fetchUrl, {
            method: 'POST',
            body: JSON.stringify(fetchParams)
        }).then(res => res.json()
        ).then(res => {
           console.log(res)
        })
    }, [])

    return (
        <>
            <button onClick={() => {setSearchID(searchID + 1)}} >button1</button>
            <button onClick={() => {onSearchInfos()}}>button2</button>
        </>
    )
}

export default Test

上述寫了一個很簡單的偽代碼功能,大致就是,點擊button1按鈕,searchID的值加1,點擊button2發送一個請求。
開始描述問題:當我們點擊了四次button1,把searchID的值更改到了4,然后點擊button2,會發現,發送出去的請求,searhID的值是0。

問題分析

為什么會產生這種問題呢?因為我們使用useCallback將請求數據的回調方法onSearchInfos包裹了一層,並且第二參數我們傳遞了一個[],表示只在組件第一次創建的時候,這個回調函數被創建,從而去提升性能!

回顧下, 我上面說到了什么?

只在第一次組件創建的時候onSearchInfos被創建!第一次!
也就是說searchID拿到的值是第一次被創建的時候,傳入的值,形成了一個閉包。

解決方案1

interface IRef {
    current: any
}

let Test = () => {
    /** Search base infos */
    const [searchID, setSearchID] = useState(0)

    /** 解決閉包問題 */
    const fetchRef: IRef = useRef() // hooks為我們提供的一個通用容器,里面有一個current屬性
    fetchRef.current = { //  為current這個屬性添加一個searchID,每當searchID狀態變更的時候,Test都會進行重新渲染,從而current能拿到最新的值
        searchID
    }

    /** Search info action */
    const onSearchInfos = useCallback(() => {
        let fetchUrl = '/api/getSearchInfos'
        let fetchParams = { ...fetchRef.current } // 解構參數,這里拿到的是外層fetchRef的引用
        fetch(fetchUrl, {
            method: 'POST',
            body: JSON.stringify(fetchParams)
        }).then(res => res.json()
        ).then(res => {
           console.log(res)
        })
    }, [])

    return (
        <>
            <button onClick={() => {setSearchID(searchID + 1)}} >button1</button>
            <button onClick={() => {onSearchInfos()}}>button2</button>
        </>
    )
}

export default Test

解決方案2

點擊查看另外一篇文章

解決方案3

據我所知,目前至少還有兩種解決方案,剛和隔壁大佬討論完,還沒來得及研究,周末研究一下,后續完善!


免責聲明!

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



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