iT邦幫忙

2022 iThome 鐵人賽

DAY 22
0

昨天會先講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,我這邊簡單列出幾個:

  1. React.FC會隱性的幫你把children推論為ReactNode型別

要是你不小心在回傳值的JSX中傳入了非預期的字串,TypeScript這時就不會報錯,你就會到執行階段才發現(或根本沒注意到)你自己傳錯值了。

const App: React.FC = () => { /*... */ };
const Example = () => {
	<App><div>Unwanted children</div></App>
}
  1. React.FC並不支援泛型
  2. 沒辦法正確的與default props配合

不過上述的說法已經是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,便能告訴你他應該要寫成什麼樣的型別了!

onChange該放的型別

這邊我們只要看冒號後面的型別就好,在不知道該怎麼寫的情況下,你就將冒號後的型別複製過去interface當中,就能解決這個狀況囉。

interface Props{
    //老實說我根本記不起來,給編輯器幫我記就好
    handleChange: React.ChangeEventHandler<HTMLInputElement>
}

const TextInput = ({handleChange}:Props) => (
    <input onChange={handleChange}>
)

const App = () => {
    return (
        <TextInput handleChange={e=>{
        //TypeScript能幫我們推薦後續屬性/方法了
        e.  //故意停在這邊不寫完
        }}/>
    )
}

event事件的相關屬性/方法

由上截圖可明顯看出,編輯器自動推薦你該事件相關的屬性/語法了!

我想,在React導入TypeScript最困難的點就在這邊吧,需要花時間去了解React提供給我們的各式型別,但若不想記也是沒關係,就透過hover到特定props,讓編輯器告訴你他“應該是”什麼型別吧。

今天先講到這邊,我覺得這很需要自己實作看看,一方面是看自己對TypeScript的書寫流程熟不熟悉、另一方面是要開始了解React所提供的各式型別。

祝大家週五愉快!明天見!


上一篇
第21天!TypeScript與React!
下一篇
第23天!TypeScript 與 useEffect!
系列文
你也對開始使用typescript感到無力嗎?我也是 - 30天初探typescript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言