不曉得大家還記不記得這個畫面:
對的,這是在 Day06 中埋下的伏筆,因為之後的 Hooks 就會開始運用 Props!所以趁現在來解決他吧!
怕幾天沒提到,不小心忘了 Props,就先來複習一下吧!
Props 通常會用在 Component 間的溝通,父層 Component 將某些資料或事件交給子層 Component,
以下舉個簡單的例子:
在使用 Hello
的時候,只要將 name
藉由 Props 傳入,Hello
在 Render 時,就可以從 Props 中取出 name
,不同的 name
傳入,就可以讓 Hello
呈現不同的樣子,這也是 React 中 Component 能重用的精髓。
但也許在使用時,我們會忘了需要傳 Props,而導致 Hello
無法 Render 出任何畫面,或是傳錯類型了,Hello
需要的是一個 String,但使用時卻傳入 Object 或 Array 導致畫面呈現的資料錯誤。
更嚴重的情況是,當資料是從資料庫過來,而等待 Response 回來前,儲存資料的變數都會是 undefined
,這時候如果又是以 map
去處理,整個網頁就會爆炸。
但是要為每個 Props 的值都寫下判斷實在是很麻煩,因此 prop-types 出現了。
npm install --save prop-types
安裝後就能夠打開專案中的 src/index.jsx:
會發現原本的警告消失了!其實它在 Day06 的最後就不再出現警告了,不曉得大家有沒有發現,其實這和 Component 內的結構有關,讓我們再看看前言那張擁有警告的圖:
看出差異了嗎?
{}
中使用,也就是在 HTML 的標籤中使用了 JavaScript,那就得為該 Props 加上類型驗證,eslint 的檢測規則是這麼一回事,但是筆者會推薦,如果情況允許,就將所有的 Props 都加上 prop-types 的規則,除了減少開發後的維護成本,
為了在解說時更清楚 prop-types 的作用,會以出現警告的版本,也就是將 names.map
移動到 div
內來說明,請大家當作練習,重新調整一下程式碼:
首先在上方為 prop-types
做 import
:
import PropTypes from 'prop-types';
接著使用 PropTypes
為每個 props
都定義型別,在 SayHello
中只接收了 names
,因此對它定義型別為陣列,且型別的內容為字串 string
:
SayHello.propTypes = {
names: PropTypes.arrayOf(PropTypes.string),
};
但這麼做 ESLint 還不滿足,因為
所以得在替他設定一個,就算使用時忽略了某個 Props,Component 也能安心 Render 的值,以 names 來說的話,就是空陣列:
SayHello.defaultProps = {
names: [],
};
這麼一來,就算使用 SayHello
時沒有賦予 names
,就不會發生錯誤,也不會 Render 讓使用者或開發人員疑惑的畫面,但是如果你期望在忽略 Props
時出現更明顯的提示,也可以這麼做:
SayHello.defaultProps = {
names: ['Default string'],
};
就會在沒有給定 names
的情況下:
ReactDom.render(
<SayHello />,
document.getElementById('root'),
);
畫面會呈現 defaultProps
設定的值:
這時候大家在試著將剛剛設定的 propTypes
和 defaultProps
先註解,就會明白忽略了 Props
會如何導致錯誤:
/* 暫時註解
SayHello.propTypes = {
names: PropTypes.arrayOf(PropTypes.string),
};
SayHello.defaultProps = {
names: ['Default string'],
};
*/
畫面會因為 names
是 undefined
而無法使用 map
,導致 Render 失敗:
最後將註解復原,並給定 names
為裝著數字的陣列:
ReactDom.render(
<SayHello names={[1, 2, 3]} />,
document.getElementById('root'),
);
雖然還是能夠正常 Render 但在瀏覽器的 console
中,就會拋出一個錯誤,告訴你目前的值為 number
,但該 Props 期望型別是 string
:
所以出現類似的 prop type
錯誤時,就得留意一下是不是有哪些 Component 在使用時傳入不正確的 Props!
本文的原始碼內容會放置於 GitHub 上,歡迎各位參考使用。
另外定義 Prop-Types 雖然麻煩,但是當網站越來越大時,能夠直接撇除掉 Props 造成的 Bug,因為要是有問題 Prop-Types 就會在 console
中告訴你錯誤,這時候就會覺得當初 Prop-Types 設定都是值得的。
如果文章中有任何問題,或是不理解的地方,都可以留言告訴我!謝謝大家!
有預先定義真的是個好習慣,維護成本也降低很多,至少可以確定不是傳遞Props的問題。
想順便請問一下神Q
SayHello.propTypes = {
names: PropTypes.arrayOf(PropTypes.string),
}
SayHello.defaultProps = {
names: ['Default String']
}
這兩段程式碼有辦法寫在一起嗎? LoL
哈哈,一個是定義 Component 的 propTypes,一個是 defaultProps,混在一起寫應該也沒有好處 XD
原來如此,看來我還是沒分清楚它們各自的用途! 謝謝神Q大!