React 快速上手 – 10 型別檢查 PropTypes

會煮咖啡的貓發表於2019-03-03
react

本系列目錄

點贊是美德 : )


React 快速上手 – 10 型別檢查 PropTypes

目標

  • 瞭解型別檢查的重要性
  • 型別檢查的使用及除錯
  • 型別檢查的一些技巧

環境

  • react 16.3.2
  • prop-types 15.6.1

我們為什麼要 型別檢查

我們先來看一份 rollbar 公司對 1000+ 專案的錯誤回收分析 top10

文章參考: Top 10 JavaScript errors from 1000+ projects

rollbar_err_top10

幾乎都是因為型別而發生的錯誤

比如定義 let prodList = [] , 你程式碼中 prodList.push(...)

但是初始的時候被設定 prodList = 123 而且沒有任何提示, 那執行 push(...) 肯定要報未知方法的錯誤

這種問題在自由的 JavaScript 世界很普遍,如果在 編譯 執行 兩個階段都沒提示的話,排錯是很麻煩的,全靠經驗和對業務的熟悉 (陳年老專案又沒文件簡直是地獄)

所以我們要把問題消滅在萌芽中,就是申明物件的時候同時把型別也定義掉了, react 的自帶方案是 PropTypes 元件

當然還有 Flow TypeScript 我個人比較喜歡 TypeScript 這在以後的進階文章我再寫

PropTypes 是一個在 編碼 階段提供型別檢查的方案 有提示總是好的,那我們開始

PropTypes 使用

老樣子,先來個基礎簡單的例子

1 簡單例子

  • 匯入包
import PropTypes from `prop-types`
複製程式碼
  • 編寫元件
class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>
  }
}
複製程式碼
  • 編寫型別檢查
Greeting.propTypes = {
  name: PropTypes.string
}
複製程式碼

設定 name 屬性型別為 string 字串

  • 容器
<div>
  <Greeting name={123} />
</div>
複製程式碼

顯然這裡設定數字和定義不一致

  • 頁面列印
Greeting-string

頁面能正常顯示,沒有錯誤,這是因為錯誤以 console 方式反饋

  • 頁面錯誤
Greeting-string-err

好吧~ 有提示就好哈~

2 不同的驗證器

// 陣列、布林、函式、數字、物件、字串、symbol
MyComponent.propTypes = {
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,

  // 任何東西都可以被渲染:numbers, strings, elements,或者是包含這些型別的陣列(或者是片段)。
  optionalNode: PropTypes.node,

  // 一個 React 元素。
  optionalElement: PropTypes.element,

  // 你也可以宣告一個 prop 是類的一個例項。
  // 使用 JS 的 instanceof 運算子。
  optionalMessage: PropTypes.instanceOf(Message),

  // 你可以宣告 prop 是特定的值,類似於列舉
  optionalEnum: PropTypes.oneOf([`News`, `Photos`]),

  // 一個物件可以是多種型別其中之一
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),

  // 一個某種型別的陣列
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  // 屬性值為某種型別的物件
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

  // 一個特定形式的物件
  optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
  }),

  // 你可以使用 `isRequired` 連結上述任何一個,以確保在沒有提供 prop 的情況下顯示警告。
  requiredFunc: PropTypes.func.isRequired,

  // 任何資料型別的值
  requiredAny: PropTypes.any.isRequired,

  // 你也可以宣告自定義的驗證器。如果驗證失敗返回 Error 物件。不要使用 `console.warn` 或者 throw ,
  // 因為這不會在 `oneOfType` 型別的驗證器中起作用。
  customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
      return new Error(
        `Invalid prop `` + propName + `` supplied to` +
        ` `` + componentName + ``. Validation failed.`
      );
    }
  },

  // 也可以宣告`arrayOf`和`objectOf`型別的驗證器,如果驗證失敗需要返回Error物件。
  // 會在陣列或者物件的每一個元素上呼叫驗證器。驗證器的前兩個引數分別是陣列或者物件本身,
  // 以及當前元素的鍵值。
  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
      return new Error(
        `Invalid prop `` + propFullName + `` supplied to` +
        ` `` + componentName + ``. Validation failed.`
      );
    }
  })
};
複製程式碼

3 限制單個子代

程式碼

// 元件
const OnlyOneChild = props => {
  const children = props.children
  return <div>{children}</div>
}
OnlyOneChild.propTypes = {
  children: PropTypes.element.isRequired
}

// 容器
<OnlyOneChild>
  <h3>第一個子節點</h3>
  <h3>第二個子節點</h3>
</OnlyOneChild>
複製程式碼

列印

OnlyOneChild

4 屬性預設值

程式碼

// 元件
const DefaultVal = props => {
  return <h3>{props.name}</h3>
}
DefaultVal.defaultProps = {
  name: `我是預設值!`
}

// 容器
<div>
  <DefaultVal />
</div>
複製程式碼

如果父元件沒有設定並傳入 namedefaultProps 將確保 this.props.name 將有一個預設值。

列印

defaultProps

程式碼

參考


© 會煮咖啡的貓咪

相關文章