当前位置: 首页 > news >正文

(四)从零学 React Props:数据传递 + 实战案例 + 避坑指南

一、为什么需要Props?—— 解决组件"定制化"问题

上节课我们学会了创建和使用组件,但有个明显的问题:组件内容是固定的。比如创建的UserCard组件,无论用多少次,都只能显示"李四"的信息;Button组件也只能显示"点击我"。

但实际开发中,组件需要根据不同场景展示不同内容:

  • 按钮可能需要显示"登录"、“注册”、"提交"等不同文字;
  • 用户卡片需要展示"张三"、"李四"等不同用户的信息;
  • 商品卡片需要展示不同商品的名称、价格、图片。

这就需要一种方式让父组件给子组件传递数据,而Props(全称Properties,属性)就是React专门用来解决这个问题的机制。

形象理解:Props就像组件的"参数"。比如你去咖啡店点咖啡(调用咖啡组件),需要告诉店员"要拿铁"(传递type="latte")、“少糖”(传递sugar="less"),店员根据这些参数制作出你要的咖啡(组件根据Props展示内容)。

二、Props的基本使用:传递与接收

Props的使用分为两步:父组件传递数据子组件接收并使用数据

1. 父组件传递Props:像写HTML属性一样简单

父组件在使用子组件时,通过"属性=值"的形式传递数据,和HTML标签的属性写法类似。

例如,父组件App要给子组件Button传递"按钮文字"和"颜色":

// 父组件 App.js
import Button from './Button';function App() {return (<div>{/* 传递Props:text是属性名,"登录"是属性值 */}<Button text="登录" color="blue" />{/* 再传一组不同的Props */}<Button text="注册" color="green" /></div>);
}export default App;
传递数据的类型:

Props可以传递任意类型的数据,包括:

  • 字符串(直接写,如text="登录");
  • 数字(需要用{}包裹,如count={5});
  • 布尔值(用{},如disabled={true});
  • 数组(用{},如list={[1,2,3]});
  • 对象(用{},如user={{name: "张三", age: 20}})。
// 传递多种类型的Props
<Button text="购买" price={99}  // 数字isNew={true}  // 布尔值tags={["热销", "新品"]}  // 数组
/>

2. 子组件接收Props:函数参数就是Props对象

函数组件通过函数的第一个参数接收父组件传递的所有Props,这个参数是一个对象,属性名就是父组件传递的属性名。

例如,Button组件接收并使用Props:

// 子组件 Button.js
// props是一个对象,包含父组件传递的所有属性(text、color等)
function Button(props) {console.log(props); // 打印看看Props内容:{ text: "登录", color: "blue" }(第一次渲染时)return (<button style={{ backgroundColor: props.color,  // 使用color属性color: "white", padding: "8px 16px",border: "none",borderRadius: "4px",margin: "0 8px"}}>{props.text}  {/* 使用text属性 */}</button>);
}export default Button;

运行后,页面会显示两个按钮:

  • 蓝色背景的"登录"按钮;
  • 绿色背景的"注册"按钮。
    这就是Props的作用:同一个组件,通过不同的Props展示不同内容。

3. 简化Props接收:解构赋值

如果Props属性很多,每次写props.textprops.color会很繁琐。可以用对象解构直接提取需要的属性,让代码更简洁。

修改Button组件:

// 用解构赋值直接提取text和color
function Button({ text, color }) {return (<button style={{ backgroundColor: color,  // 直接用color// 其他样式...}}>{text}  {/* 直接用text */}</button>);
}

效果和之前完全一样,但代码更简洁。这是React开发中最常用的写法,一定要掌握。

三、Props的核心特性:只读性(不可修改!)

这是React的重要原则:子组件不能修改接收到的Props,Props是"只读的"(read-only)。

为什么Props不能修改?

  • Props的数据来源是父组件,修改Props会导致数据流向混乱(父组件和子组件都可能改数据,难以追踪);
  • React通过"单向数据流"(父→子)保证数据可预测性,方便调试和维护。

错误示例:尝试修改Props

function Button({ text }) {// 尝试修改Props(会报错!)text = "新文字";  // 错误:Props是只读的,不能重新赋值return <button>{text}</button>;
}

运行后控制台会报错,提示"Assignment to constant variable"(给常量赋值),因为Props被视为不可变数据。

正确做法:如果需要修改,用子组件自己的状态

如果子组件需要修改数据,应该把数据存在子组件的"状态"(State)中,这部分我们下节课会详细讲。Props只负责"接收外部数据",不负责"存储内部可变数据"。

四、Props默认值:给组件设置"默认参数"

如果父组件使用子组件时没有传递某个Props,子组件可以设置默认值,避免出现undefined

设置默认值有两种方式:

1. 函数参数默认值(推荐,简单直观)

直接在解构赋值时给属性设置默认值:

// 给color设置默认值"gray",text设置默认值"按钮"
function Button({ text = "按钮", color = "gray" }) {return (<button style={{ backgroundColor: color }}>{text}</button>);
}

当父组件不传递Props时,会使用默认值:

// 父组件中不传递text和color
<Button />  // 会显示灰色背景的"按钮"

2. 组件的defaultProps属性(了解即可)

这是另一种设置默认值的方式,通过组件的defaultProps属性:

function Button({ text, color }) {return (<button style={{ backgroundColor: color }}>{text}</button>);
}// 设置默认Props
Button.defaultProps = {text: "按钮",color: "gray"
};

效果和函数参数默认值一样,但现在更推荐用第一种方式(更简洁,符合ES6语法)。

五、Props类型检查:让组件更健壮(基础版)

大型项目中,为了避免传递错误类型的Props(比如应该传数字却传了字符串),可以给Props做类型检查。React推荐用prop-types库来实现。

步骤1:安装prop-types

在终端中进入项目目录,执行安装命令:

npm install prop-types --save

步骤2:在组件中使用类型检查

Button组件为例,限制text是字符串,color是字符串,price是数字:

import PropTypes from 'prop-types';  // 导入PropTypesfunction Button({ text, color, price }) {return (<button style={{ backgroundColor: color }}>{text} {price && `¥${price}`}</button>);
}// 定义Props类型检查规则
Button.propTypes = {text: PropTypes.string,  // text必须是字符串color: PropTypes.string, // color必须是字符串price: PropTypes.number  // price必须是数字
};export default Button;

如果父组件传递错误类型(比如price="99",字符串),控制台会警告:
Warning: Failed prop type: Invalid prop 'price' of type 'string' supplied to 'Button', expected 'number'.

常用类型检查规则:

  • PropTypes.string:字符串
  • PropTypes.number:数字
  • PropTypes.bool:布尔值
  • PropTypes.array:数组
  • PropTypes.object:对象
  • PropTypes.func:函数
  • PropTypes.node:可以渲染的内容(数字、字符串、元素等)
  • PropTypes.isRequired:必须传递的属性(在类型后加,如PropTypes.string.isRequired
Button.propTypes = {text: PropTypes.string.isRequired,  // text必须传递,且是字符串price: PropTypes.number  // price可选,但如果传必须是数字
};

如果父组件没传递text(加了isRequired),会警告:Warning: Failed prop type: The prop 'text' is marked as required in 'Button', but its value is 'undefined'.

六、综合案例:用户列表组件(复用+Props传递)

我们来创建一个UserList父组件,传递多个用户数据给UserCard子组件,展示用户列表。

步骤1:改造UserCard组件(接收Props)

// src/UserCard.js
import PropTypes from 'prop-types';// 接收用户数据作为Props
function UserCard({ user }) {return (<div style={{ border: '1px solid #ddd', padding: '16px', borderRadius: '8px', margin: '8px',maxWidth: '200px'}}><img src={user.avatar} alt={user.name} style={{ width: '80px', borderRadius: '50%' }}/><h3>{user.name}</h3><p>{user.age}岁 | {user.gender}</p><p>{user.bio}</p></div>);
}// 类型检查
UserCard.propTypes = {user: PropTypes.shape({  // 检查对象内部属性name: PropTypes.string.isRequired,avatar: PropTypes.string.isRequired,age: PropTypes.number.isRequired,gender: PropTypes.string,bio: PropTypes.string}).isRequired  // user必须传递
};export default UserCard;

步骤2:创建UserList组件(传递Props)

// src/UserList.js
import UserCard from './UserCard';function UserList() {// 模拟用户数据(实际项目可能来自接口)const users = [{name: "张三",avatar: "https://picsum.photos/id/1/200",age: 25,gender: "男",bio: "前端工程师"},{name: "李四",avatar: "https://picsum.photos/id/2/200",age: 23,gender: "女",bio: "UI设计师"},{name: "王五",avatar: "https://picsum.photos/id/3/200",age: 28,gender: "男",bio: "产品经理"}];return (<div style={{ display: 'flex', flexWrap: 'wrap' }}>{/* 遍历用户数据,给每个UserCard传递不同的user */}{users.map((user, index) => (<UserCard key={index} user={user} />  {/* 传递user对象作为Props */}))}</div>);
}export default UserList;

步骤3:在App中使用UserList

// src/App.js
import UserList from './UserList';function App() {return (<div style={{ padding: '20px' }}><h1>用户列表</h1><UserList /></div>);
}export default App;

运行效果:

页面会显示3个用户卡片,每个卡片展示不同用户的信息(姓名、头像、年龄等)。通过Props,我们实现了UserCard组件的复用,只写一次组件,就能展示不同数据。

七、常见问题与解决办法

  1. Props传递后显示undefined
    可能原因:

    • 父组件传递的属性名和子组件接收的不一致(比如父传username,子取name);
    • 子组件没正确解构Props(比如写成{ userName }但实际属性是userName)。
      解决:检查属性名拼写,用console.log(props)在子组件中打印Props,确认数据是否传递成功。
  2. 传递数字/布尔值时显示错误
    错误写法:<Button count="5" />(会被当作字符串"5")
    解决:用{}包裹非字符串类型:<Button count={5} isActive={true} />

  3. 忘记安装prop-types导致报错
    报错:Cannot find module 'prop-types'
    解决:在终端执行npm install prop-types --save安装依赖。

http://www.dtcms.com/a/512635.html

相关文章:

  • 上传自己做的网站吗关键词优化百家号
  • 连云港做网站公司校园网的规划与设计
  • DeepSeek-OCR:视觉压缩的革命性突破——当OCR遇上LLM的“降维打击“
  • 盐城网站开发市场做网站怎么去工信部缴费
  • ps做游戏网站伊宁网站建设优化
  • 【高等数学笔记-极限(7)】函数连续
  • !for_each_process 命令详解
  • 住房与城乡建设网站引流客户的最快方法是什么
  • 江西网站开发的公司wordpress插件看访问者数量
  • 10.21
  • SharedFlow和StateFlow的方案选择-屏幕旋转设计
  • ps做素材下载网站有哪些wordpress用什么框架
  • 网站建设除凡科外还有哪些wordpress主题 添加自定义菜单
  • 怎么做视频网站教程什么是网络营销报价
  • DMA直接存储器访问
  • 电话销售怎么做 网站临沂森拓网络科技有限公司
  • 在网上招标做兼职的网站建设网站装配式建筑楼房
  • 360°客户视图:MDM/CDP如何驱动实时个性化服务?
  • JavaScript 与 React 工程化实践对比
  • 【完整源码+数据集+部署教程】【天线&其他】建筑损毁程度检测评估系统源码&数据集全套:改进yolo11-Parc
  • 24991-53-5,Amine-PEG-Amine的化学结构与反应活性
  • Java:创建、读取或更新 Excel 文档
  • 广州免费建站找哪家网站企业备案资料
  • (二)Flutter插件之Android插件开发
  • 贵港seo关键词整站优化ps如何做psd模板下载网站
  • 雄安做网站优化的公司企业官方网站的作用
  • 中国建设行业峰会官方网站营销公司有哪些
  • 用wireshark进行手机app抓包教程-2025最新
  • 建设网站应注意什么河北提供网站建设公司电话
  • Ubuntu22.04-Cuda12.1 安装 Detectron2