昨天看完了簡單的useEffect
,前天也看了useState
,今天再來看點差不多簡單的:useRef
。
我們都是在要對某一HTML元素進行操作、或者是記住某個元素的reference時,才會使用到useRef
。比方說對一個input進行聚焦(focus)、或者說在讀取完頁面時,對特定div使用element.scrollIntoView()
讓div出現在畫面"中"等等的。
那我們來看看怎麼用吧:
import { useRef } from "react"
const App = () => {
const inputRef = useRef(null)
return <input type="text" ref={inputRef} />
}
export default App
好了,我們成功使用了useRef
,TypeScript也沒有報錯。
那我們明天見~~~
開玩笑的,但useRef差不多就這麼簡單,TypeScript也真的不會報錯。
畢竟,TypeScript會自動幫我們推論inputRef
的型別。const inputRef: React.MutableRefObject<null>
我們得到的是一個MutableRefObject
,也就是可變的Ref物件。
去看一下定義,你會得到:
interface RefObject<T> {
readonly current: T | null;
}
發現了之前看過的唯讀關鍵字!以及current應該代表的型別必須是T或者null。
那我們缺什麼?我們最好主動帶給他一個型別,一個更精確的型別,上面泛型中的T,編輯器在後續的撰寫便能幫我們推薦更理想的屬性/方法:
const inputRef = useRef<HTMLInputElement>(null)
這時我們的inputRef
就變成了下面這型別:const inputRef: React.RefObject<HTMLInputElement>
舉例而言,如果我們要在元件渲染後,對input進行聚焦,就只要這樣:
useEffect(()=>{
inputRef.current.focus()
},[])
但你如果實際這樣做的話,你會發現TypeScript報錯了,因為:
1.我們賦予inputRef
的起始值是null
2.因為起始值是null
,也就表示inputRef.current
有可能是null
所以我們這邊要進行型別防衛,你可以:
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus()
}
}, [])
//或者
useEffect(() => {
inputRef.current?.focus()
}, [])
//題外話,你也可以輸入
//inputRef.current.
//看看編輯器提供了你哪些屬性/方法,滿好玩的
兩者都能達到效果,且編輯器也完全不會報錯。
你會發現這非常的簡單,簡單到有點不需要講,但我們透過查找定義、透過主動宣告型別,不僅了解了更多hook的內容,也得到了編輯器更多的幫助,長久下來必能節省我們寫code、debug的時間。
那今天就先講到這邊,非常建議你將ref放到不同的HTML element當中,看一下他會報出什麼錯、該怎麼修正?編輯器又會推薦哪些屬性/方法?
(寫的當下是連假第二天,趕快寫完才能趕快外出走走!)
附註:下面是編輯器會推薦的inputRef.current
的屬性/方法
不曉得你有沒有注意過,清單當中的icon,藍色長方體icon是屬性property、紫色正方體icon是方法method。