向组件传递 Props
React 组件通过props进行相互通信。每个父组件都可以通过向子组件传递 props 来传递一些信息。Props 可能会让你想起 HTML 属性,但你可以通过它们传递任何 JavaScript 值,包括对象、数组和函数。
您将学习
- 如何向组件传递 props
- 如何从组件读取 props
- 如何为 props 指定默认值
- 如何向组件传递一些 JSX
- Props 如何随时间变化
熟悉的 props
Props 是你传递给 JSX 标签的信息。例如,className、src、alt、width 和 height 是你可以传递给 <img>的一些 props:
你可以传递给 <img>标签的 props 是预定义的(ReactDOM 遵循HTML 标准)。但你可以向 你自己的组件传递任何 props,例如<Avatar>,以自定义它们。方法如下!
向组件传递 props
在这段代码中,Profile 组件没有向其子组件 Avatar传递任何 props:
你可以通过两个步骤给Avatar传递一些 props。
步骤 1:向子组件传递 props
首先,向 Avatar传递一些 props。例如,让我们传递两个 props:person(一个对象)和size(一个数字):
注意
如果 person=后面的双花括号让你困惑,请回想它们仅仅是 JSX 花括号内的一个对象。
现在你可以在 Avatar组件内部读取这些 props。
步骤 2:在子组件内部读取 props
你可以通过在 function Avatar之后直接列出它们的名称person, size(用逗号分隔)并放在({ 和 })中来读取这些 props。这让你可以在Avatar代码内部使用它们,就像使用变量一样。
向 Avatar添加一些使用person 和 sizeprops 进行渲染的逻辑,你就完成了。
现在你可以通过不同的 props 来配置Avatar,使其以多种不同的方式渲染。尝试调整这些值!
Props 让你可以独立地思考父组件和子组件。例如,你可以在 Profile内部更改person 或 sizeprops,而无需考虑Avatar如何使用它们。同样,你也可以更改Avatar如何使用这些 props,而无需查看Profile。
你可以将 props 视为可以调整的“旋钮”。它们的作用与函数参数的作用相同——事实上,props就是你组件的唯一参数!React 组件函数接受一个参数,即一个props对象:
通常你不需要整个 props对象本身,因此你可以将其解构为单独的 props。
陷阱
为 prop 指定默认值
如果你想为 prop 指定一个默认值,以便在未指定值时回退使用,可以通过在参数后放置= 和默认值来进行解构:
现在,如果渲染<Avatar person={...} /> 时没有 sizeprop,size将被设置为100。
默认值仅在 sizeprop 缺失或你传递size={undefined}时使用。但如果你传递size={null} 或 size={0},默认值将 不会被使用。
使用 JSX 展开语法传递 props
有时,传递 props 会变得非常重复:
重复的代码本身没有问题——它可能更具可读性。但有时你可能更看重简洁性。有些组件会将其所有 props 传递给它们的子组件,就像这个Profile 组件对 Avatar所做的那样。因为它们不直接使用任何 props,所以使用更简洁的“展开”语法可能更有意义:
这将 Profile的所有 props 传递给Avatar,而无需逐一列出它们的名称。
请谨慎使用展开语法。如果你在每个其他组件中都使用它,那可能有问题。通常,这表明你应该拆分组件并将子组件作为 JSX 传递。接下来会详细介绍!
将 JSX 作为子组件传递
嵌套内置的浏览器标签是很常见的:
有时你会希望以同样的方式嵌套你自己的组件:
当你在 JSX 标签中嵌套内容时,父组件将在名为 children的 prop 中接收该内容。例如,下面的Card 组件将接收到一个 childrenprop,其值为<Avatar />,并在一个包装 div 中渲染它:
尝试将 <Avatar>替换为一些文本,看看<Card>组件如何包装任何嵌套内容。它不需要“知道”内部渲染的是什么。你会在许多地方看到这种灵活的模式。
你可以将带有 childrenprop 的组件视为有一个“洞”,可以由其父组件用任意 JSX 来“填充”。你通常会为视觉包装器使用children prop:面板、网格等。

Props 如何随时间变化
下面的Clock 组件从其父组件接收两个 props:color 和 time。(父组件的代码被省略了,因为它使用了state,我们暂时不会深入探讨。)
尝试在下面的选择框中更改颜色:
这个例子说明了 组件可能会随时间接收不同的 props。Props 并不总是静态的!在这里,timeprop 每秒变化一次,而colorprop 在你选择另一种颜色时变化。Props 反映了组件在任何时间点的数据,而不仅仅是在开始时。
然而,props 是不可变的——这是一个来自计算机科学的术语,意思是“不可更改”。当组件需要更改其 props 时(例如,响应用户交互或新数据),它必须“请求”其父组件传递不同的 props——一个新的对象!然后它的旧 props 将被丢弃,最终 JavaScript 引擎将回收它们占用的内存。
不要尝试“更改 props”。 当你需要响应用户输入(例如更改所选颜色)时,你将需要“设置状态”,你可以在 State: A Component’s Memory 中学习。
回顾
- 要传递 props,请将它们添加到 JSX 中,就像处理 HTML 属性一样。
- 要读取 props,请使用
function Avatar({ person, size })解构语法。 - 你可以指定一个默认值,例如
size = 100,它用于缺失和undefined的 props。 - 你可以使用
<Avatar {...props} />JSX 展开语法转发所有 props,但不要过度使用它! - 嵌套的 JSX,如
<Card><Avatar /></Card>将作为Card组件的childrenprop 出现。 - props 是只读的时间快照:每次渲染都会接收到一个新版本的 props。
- 你不能更改 props。当你需要交互性时,你需要设置状态。
Try out some challenges
Challenge 1 of 3:Extract a component #
This Gallery component contains some very similar markup for two profiles. Extract a Profile component out of it to reduce the duplication. You’ll need to choose what props to pass to it.
