(11)React 进阶——① PropTypes 和 DefaultProps 讲解 | React 基础理论实操

复制代码
转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥"前端一万小时"两大明星专栏------"从零基础到轻松就业"、"前端面试刷题",已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。

javascript 复制代码
涉及面试题:
1. 静态类型检查推荐的方法是什么?
2. 什么是 PropTypes?
3. 什么是 React proptype 数组?

[编号:react_11]

1 PropTypes

通过之前的学习,我们知道每个子组件都有自己的 props 参数,这个参数是从父组件接收的一些"属性"。

本篇我们会讲解:子组件在接收参数时,应该如何对参数的"类型"做校验,如何定义参数的"默认值"。

❓需求:我要使父组件传给子组件的值必须符合子组件规定的某种"类型",不能乱传(这也是我们开发过程中需要做的一点)。

答: 1️⃣打开 TodoItem.js 文件,我们可以看到父组件传过来的"值"。

这些"值"都有属于自己的"类型":

2️⃣子组件引入 PropTypes 对传递过来的属性做一个"类型"的强校验:

jsx 复制代码
import React, { Component } from "react";

import PropTypes from "prop-types"; /*
																		2️⃣-①:由于脚手架工具里边已经自带了 prop-types 这个包,
																		所以我们可以直接引入 PropTypes;
                                    ❗️❗️❗️注意大小写!
                                     */  

class TodoItem extends Component {
  constructor(props) {
    super(props);
    
    this.handleClick = this.handleClick.bind(this);
  } 
  
  render() {
    const {content} = this.props
    
    return(
      <div onClick={this.handleClick}> 
        {content}  
      </div>
    )
  }
  
  handleClick() {  
    const {itemDelete, index} = this.props
    
    itemDelete(index)
  }
}

TodoItem.propTypes = { // 2️⃣-②:这行代码表示对 TodoItem 这个组件做"属性"的校验;
	
  // 2️⃣-③:分别对以下属性做校验;
  content: PropTypes.string, /*
  													 2️⃣-④:这行代码表示,content 这个 prop,
  													 它的"类型"必须是一个 string 类型;
                             ❗️❗️❗️注意这里的大小写!
                              */
  
  itemDelete: PropTypes.func,
  index: PropTypes.number
}

export default TodoItem;

返回页面看下效果(没任何报错,因为父组件所传的值,都符合子组件要求的"类型"):

❌但,如果我在子组件里要求 index 的类型为 string ,这时页面就会给我们报"警告"(因为父组件传过来的是 number 类型,但你子组件却要 string 类型):

javascript 复制代码
index: PropTypes.string

2 DefaultProps

紧接上文的代码,我们有一个新的需求:

在子组件里,子组件必须要求父组件给它传递一个"属性"(如 test ),但父组件因某些原因,确实不能传递这个 test 。此时应该怎么解决呢?

jsx 复制代码
import React, { Component } from "react";

import PropTypes from "prop-types";

class TodoItem extends Component {
  constructor(props) {
    super(props);
    
    this.handleClick = this.handleClick.bind(this);
  } 
  
  render() {
    const {content, test} = this.props /*
    																	 1️⃣
    																	 1️⃣-①:在子组件里,
                                       子组件要求父组件给它传递一个"属性"test;
                                        */
    
    return(
      <div onClick={this.handleClick}> 
      	{test}-{content} {/* 1️⃣-②:并且,想把 test 展示在页面上; */}
      </div>
    )
  }
  
  handleClick() {  
    const {itemDelete, index} = this.props  
    
    itemDelete(index)
  }
}

TodoItem.propTypes = {
  
  test: PropTypes.string.isRequired, /*
  																	 1️⃣-③:这个"属性"test 的"类型"是 string,
   																	 且是"必须"的。
                                      */
  
  content: PropTypes.string,  
  itemDelete: PropTypes.func,
  index: PropTypes.number
}

export default TodoItem;

我们看看页面效果(控制台报了"警告",因为父组件确实没有传递这个 test 属性,但子组件又规定必须要,所以程序给我们报了警告!):

❓怎么解除上边的"警告"呢?

答: 2️⃣在 TodoItem 里,给属性 test 定义一个"默认值";

jsx 复制代码
import React, { Component } from "react";

import PropTypes from "prop-types";

class TodoItem extends Component {
  constructor(props) {
    super(props);
    
    this.handleClick = this.handleClick.bind(this);
  } 
  
  render() {
    const {content, test} = this.props 
    
    return(
      <div onClick={this.handleClick}> 
      {test}{content}  
      </div>
    )
  }
  
  handleClick() {  
    const {itemDelete, index} = this.props  
    
    itemDelete(index)
  }
}

TodoItem.propTypes = {
  
  test: PropTypes.string.isRequired, 
  
  content: PropTypes.string,  
  itemDelete: PropTypes.func,
  index: PropTypes.number
}

TodoItem.defaultProps = { // 2️⃣-①:给 TodoItem 增添一些"默认属性";
  
  test: "hello, " /*
  								2️⃣-②:比如增加一个默认属性 test,其值为 "hello, " 。
  								表示,即使父组件没办法给我子组件传递这个 test 属性,我子组件依然能够
                  使用 test 属性,因为我自己定义了一个"默认值"。
  								 */
}

export default TodoItem;

查看页面效果("警告"解除,且显示出了"默认值" hello, ):

🔗本文知识点对应"官方文档"

可在彻底掌握本文的基础上,去阅读官方英文文档加深理解!

祝好,qdywxs ♥ you!

相关推荐
橙露5 分钟前
Webpack/Vite 打包优化:打包体积减半、速度翻倍
前端·webpack·node.js
chushiyunen9 分钟前
python中的魔术方法(双下划线)
前端·javascript·python
楠木68524 分钟前
从零实现一个 Vite 自动路由插件
前端
终端鹿34 分钟前
Vue2 迁移 Vue3 避坑指南
前端·javascript·vue.js
进击的尘埃38 分钟前
Signals 跨框架收敛:TC39 提案、Solid、Angular、Preact 的实现差异与调度策略对比
javascript
程序员陆业聪39 分钟前
工程师的瓶颈,已经不是代码了
前端
毛骗导演1 小时前
@tencent-weixin/openclaw-weixin 源码ContextToken 持久化改造:实现微信自定义消息发送能力
前端·架构
爱丽_1 小时前
Pinia 状态管理:模块化、持久化与“权限联动”落地
java·前端·spring
进击的尘埃1 小时前
从多仓到 Monorepo 的渐进式迁移:Git 历史保留、依赖收敛与缓存调优
javascript
SuperEugene1 小时前
TypeScript+Vue 实战:告别 any 滥用,统一接口 / Props / 表单类型,实现类型安全|编码语法规范篇
开发语言·前端·javascript·vue.js·安全·typescript