不曉得大家還記不記得這個畫面:

對的,這是在 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大!