昨天會先講useState
,是因為他應該是學React的人最早碰到的hook,使用上也不會太困難,畢竟他就是對一個變數進行型別註解而已,除非你的初始值跟與後續可能變更的值相對複雜,不然真的算是很平易近人的開頭,而且由於TypeScript會幫你進行型別推論,導致我們不用主動宣告型別,便能享有TypeScript幫我們進行後續檢查了,相當方便。
今天回過頭來,看一下props
怎麼設定好了。
interface Props{
message: string
}
//解構props,並讓TypeScript去推論回傳值的型別(JSX.Element)
const App = ({message}: Props ) => <div>{message}</div>
//你也能主動指定回傳值的型別,以React例子來講,不太必要
//主動指定後,當你不小心回傳了"非"JSX Element的值時,就會報錯
//但這發生機率太低了
const App = ({message}: Props ): JSX.Element => <div>{message}</div>
//Error!! 類型 'string' 不可指派給類型 'Element'。
const App = ({message}: Props): JSX.Element => "Random text"
//你也能用inline的方式寫出來,但就煩瑣一點、不能重複利用
const App = ({message}: {message: string}) => <div>{message}</div>
如果你跟我一樣是在先前就看過TypeScript的人,應該會對另一個回傳值型別比較有印象:
//或者React.FC
const App:React.FunctionComponent<{message: string}> = ({message}) => (
<div>{message}</div>
);
這樣的語法在先前(兩三年前)被寫進了create-react-app裏面作為範例,導致當時你可以在許多地方都援引了這個例子,但其實這樣的寫法,在前陣子(React 18以前)幾乎沒有可取之處,可以詳閱issue#8177,我這邊簡單列出幾個:
children
推論為ReactNode型別要是你不小心在回傳值的JSX中傳入了非預期的字串,TypeScript這時就不會報錯,你就會到執行階段才發現(或根本沒注意到)你自己傳錯值了。
const App: React.FC = () => { /*... */ };
const Example = () => {
<App><div>Unwanted children</div></App>
}
不過上述的說法已經是2020年1月的事情了,在React 18、TypeScript5.1以後,這些bug已經被修正了,React.FC已經不會主動將children
推論為ReactNode
,所以你可以安心的使用它,或者乾脆讓TypeScript幫你推論回傳值的型別就好。可以參考這篇文章或這篇
所以簡單來說,我們在對props
進行的設定,其實跟設定一般的物件並無二致,但還是得注意原始值以外的型別,這邊再舉一個例子:props
中的handleChange
函式。
interface Props{
//先宣告一個不正確的handleChange型別
handleChange: () => void,
}
const TextInput = ({handleChange}:Props) => (
<input onChange={handleChange}>
)
上面我們這樣寫,TypeScript是完全不會報錯的,但寫過React就知道,input
當中的onChange
事件是要帶入一個event
的。知道這個以後,然後呢?要怎麼寫?React的相關型別...我們沒有介紹到,要一個一個翻是不是有點累?這邊我們只要將滑鼠移動到onChange
字樣上並hover,便能告訴你他應該要寫成什麼樣的型別了!
這邊我們只要看冒號後面的型別就好,在不知道該怎麼寫的情況下,你就將冒號後的型別複製過去interface
當中,就能解決這個狀況囉。
interface Props{
//老實說我根本記不起來,給編輯器幫我記就好
handleChange: React.ChangeEventHandler<HTMLInputElement>
}
const TextInput = ({handleChange}:Props) => (
<input onChange={handleChange}>
)
const App = () => {
return (
<TextInput handleChange={e=>{
//TypeScript能幫我們推薦後續屬性/方法了
e. //故意停在這邊不寫完
}}/>
)
}
由上截圖可明顯看出,編輯器自動推薦你該事件相關的屬性/語法了!
我想,在React導入TypeScript最困難的點就在這邊吧,需要花時間去了解React提供給我們的各式型別,但若不想記也是沒關係,就透過hover到特定props,讓編輯器告訴你他“應該是”什麼型別吧。
今天先講到這邊,我覺得這很需要自己實作看看,一方面是看自己對TypeScript的書寫流程熟不熟悉、另一方面是要開始了解React所提供的各式型別。
祝大家週五愉快!明天見!