关于React-Native(React)中的类型检查

类型检查

为什么要类型检查

我们先来看一份 rollbar 公司对 1000+ 项目的错误回收分析 top10 几乎都是因为类型而发生的错误

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

比如定义 let prodList = [] , 你代码中 prodList.push(...)

但是初始的时候被设置 prodList = 123 而且没有任何提示, 那运行 push(...) 肯定要报未知方法的错误

这种问题在自由的 JavaScript 世界很普遍,如果在 编译 运行 两个阶段都没提示的话,排错是很麻烦的,全靠经验和对业务的熟悉 (陈年老项目又没文档简直是地狱)

所以我们要把问题消灭在萌芽中,就是申明对象的时候同时把类型也定义掉了, react 的自带方案是 PropTypes 组件

摘自:React 快速上手 - 10 类型检查 PropTypes

  • 类型错误(TypeError)是JavaScript世界很普遍的一种错误
  • 类型错误 在编译运行 两个阶段都没有提示,由于JS的这个特性,这种错误排错比较麻烦
  • 解决方案:
    • 可以使用 FlowTypeScript 等 JavaScript 扩展来对整个应用程序做类型检查
    • React 也内置了一些类型检查的功能,自带方案是 PropTypes 组件

PropTypes--React的类型检查方案

注意:
自 React v15.5 起,React.PropTypes 已移入另一个包中。请使用prop-types库代替。

特性

  • PropTypes 提供一系列验证器,可用于确保组件接收到的数据类型是有效的
  • 当传入的 prop 值类型不正确时,JavaScript 控制台将会显示警告
  • 出于性能方面的考虑,propTypes 仅在开发模式下进行检查。
  • PropTypes必须要用static声明(或类属性),否则无效果。
  • PropTypes 只能用于React框架的自定义组件,默认JS是没有的,因为它是React框架中的。

使用方式

要在组件的 props 上进行类型检查,你只需配置特定的 propTypes 属性:(即设置类的静态属性propTypes

import PropTypes from 'prop-types';

//写法一:
class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}
//设置propTypes静态(类)属性
Greeting.propTypes = {
  name: PropTypes.string
};



//写法二:(ES7)写法
class Greeting extends React.Component {
    //设置propTypes静态(类)属性
    static propTypes = {
        name: PropTypes.string,
        onFlipEnd: PropTypes.func,
        isFlipped: PropTypes.bool,
   };
    
   render() {
        return (
            <h1>Hello, {this.props.name}</h1>
        );
   }
    
}

检查器列举

以下是各种验证器的示例

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  // 你可以将属性声明为 JS 原生类型,默认情况下
  // 这些属性都是可选的。
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,

  // 任何可被渲染的元素(包括数字、字符串、元素或数组)
  // (或 Fragment) 也包含这些类型。
  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
  }),

  // 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
  // 这个 prop 没有被提供时,会打印警告信息。
  requiredFunc: PropTypes.func.isRequired,

  // 任意类型的数据
  requiredAny: PropTypes.any.isRequired,

  // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
  // 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。
  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.'
      );
    }
  })
};

你可以通过 PropTypes.element 来确保传递给组件的 children 中只包含一个元素

import PropTypes from 'prop-types';

class MyComponent extends React.Component {
  render() {
    // 这必须只有一个元素,否则控制台会打印警告。
    const children = this.props.children;
    return (
      <div>
        {children}
      </div>
    );
  }
}

MyComponent.propTypes = {
  children: PropTypes.element.isRequired
};

默认 Prop 值(defaultProps)

可以通过配置特定的 defaultProps 属性来定义 props 的默认值:

//写法一(ES6):
class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

// 指定 props 的默认值:
Greeting.defaultProps = {
  name: 'Stranger'
};


//写法二(ES7):
class Greeting extends React.Component {
  static defaultProps = {
    name: 'stranger'
  }

  render() {
    return (
      <div>Hello, {this.props.name}</div>
    )
  }
}


// 渲染出 "Hello, Stranger":
ReactDOM.render(
  <Greeting />,
  document.getElementById('example')
);

defaultProps 用于确保 this.props.name 在父组件没有指定其值时,有一个默认值。propTypes 类型检查发生在 defaultProps 赋值后,所以类型检查也适用于 defaultProps。

参考资料: 使用 PropTypes 进行类型检查ReactNative之PropTypes(七)React 快速上手 - 10 类型检查 PropTypes

推荐阅读更多精彩内容

  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 8,086评论 1 33
  • 以下内容是我在学习和研究React时,对React的特性、重点和注意事项的提取、精练和总结,可以做为React特性...
    科研者阅读 7,633评论 2 21
  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,562评论 1 18
  • 为了帮助大家快速上手React Native开发,在这本节中将向大家介绍开发React Native所需要的一些R...
    CrazyCodeBoy阅读 1,460评论 1 9
  • GUIDS 第一章 为什么使用React? React 一个提供了用户接口的JavaScript库。 诞生于Fac...
    jplyue阅读 3,267评论 1 11
  • 一、没有目的,没有选择,非理性的无效读书; 二、没有建立对书的整体认知框架; 三、没有理解书(作者)的核心观点或结...
    快乐番茄阅读 228评论 0 0
  • 1月25号复盘 早起 ✅ 5:55完成 每天三目标 1.专业知识 《分析化学》✅ 2.听《精力管理课》✅ 3.复盘...
    明明陪你坚持阅读 159评论 0 6
  • 4月19日的机票,20日抵达珠海,在家过了一天,22日回到武汉,参加了两个会议,见到一些中国的学者和专家。厦大的一...
    书女经阅读 167评论 0 0