?
1. useRef(保存引用值)
useRef
通常用于保存“不會參與 UI 渲染,但生命周期要長”的對象引用,比如獲取 DOM、保存定時器 ID、WebSocket等。
新建useRef.js
組件,寫入代碼:
import React, { useRef, useState } from 'react'export default function UseRef() {const name = useRef<HTMLInputElement>(null)let [list, setList] = useState(['000', '111', '222'])let btnHandle = () => {if (name.current) {setList([...list, name.current.value])name.current.value = ''}}let delHandle = (index: number) => {let temList = [...list]temList.splice(index, 1)setList(temList)}return (<div><input ref={name} /><button onClick={btnHandle}>click</button><ul>{list.map((value, index) => {return (<li key={index}>{value}<button onClick={() => delHandle(index)}>刪除</button></li>)})}</ul></div>)
}
上面的name會保存引用值,可以帶入到點擊事件,效果:?
不僅如此,useRef
還能在函數組件中保持狀態:
import React, { useState, useRef } from 'react'export default function UseRef() {const [count, setCount] = useState(0)let myCount = useRef(0)const addHandle = () => {setCount(count + 1)myCount.current++}return (<div><button onClick={addHandle}>click</button>{count} - {myCount.current}</div>)
}
上面的myCount當值變化時,能夠實時保存。
2.?useCallback(記憶函數)
防止因為組件重新渲染,導致方法被重新創建,起到緩存作用,只有第二個參數變化了,才重新聲明一次。
新建?UseCallback.js
方法組件,寫入代碼:
import React, { useCallback, useEffect } from 'react'export default function UseCallback() {const [userId, setUserId] = useState(1)const [user, setUser] = useState<any>(null)const [counter, setCounter] = useState(0)const fetchUser = useCallback(() => {console.log(`Fetching user with ID ${userId}...`)fetch(`https://jsonplaceholder.typicode.com/users/${userId}`).then(res => res.json()).then(data => setUser(data))}, [userId])useEffect(() => {fetchUser()}, [fetchUser])return (<div><h2>用戶信息</h2>{user ? (<div><p>名字: {user.name}</p><p>郵箱: {user.email}</p></div>) : (<p>加載中...</p>)}<button onClick={() => setUserId(id => id + 1)}>切換用戶</button><button onClick={() => setCounter(c => c + 1)}>其他按鈕(不影響 fetch)</button><p>Counter: {counter}</p></div>)
}export default UseCallback
上面僅當 userId 變化時,fetchUser 函數才會變化,userId 不變就不重新生成函數。效果:?
如果不使用 useCallback
,每次渲染時函數都會創建,這在傳給子組件或放到 useEffect
/ onClick
等地方時,會帶來性能浪費、重復渲染、無法復用的問題。
3.?useMemo(記憶組件)
useMemo
是 值級緩存,用于緩存變量、數組、對象、計算結果,不同于 useCallback
是 函數級緩存。
import React, { useState, useMemo } from 'react'const UserList = () => {const [query, setQuery] = useState('')const [users] = useState(['Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank', 'George'])const filteredUsers = useMemo(() => {console.log('Filtering...')return users.filter(user => user.toLowerCase().includes(query.toLowerCase()))}, [query, users])return (<div><inputplaceholder="搜索用戶"value={query}onChange={(e) => setQuery(e.target.value)}/><ul>{filteredUsers.map((user, index) => (<li key={index}>{user}</li>))}</ul></div>)
}export default UserList
結果:
?上面只有當 query 或 users 變化時,才重新過濾;如果不使用 useMemo,
每次組件渲染時,users.filter(...)
都會執行一次,即使輸入沒有變。