Pasar props a un componente
Los componentes de React utilizan props para comunicarse entre sí. Cada componente padre puede enviar información a sus componentes hijos mediante el uso de props. Las props pueden parecerte similares a los atributos HTML, pero permiten pasar cualquier valor de JavaScript a través de ellas, como objetos, arrays y funciones.
Aprenderás
- Cómo pasar props a un componente
- Cómo acceder a las props desde un componente
- Cómo asignar valores predeterminados para las props
- Cómo pasar código JSX a un componente
- Cómo las props cambian con el tiempo
Props conocidas
Las props son los datos que se pasan a un elemento JSX. Por ejemplo, className
, src
, alt
, width
y height
son algunas de las props que se pueden pasar a un elemento <img>
:
function Avatar() { return ( <img className="avatar" src="https://i.imgur.com/1bX5QH6.jpg" alt="Lin Lanying" width={100} height={100} /> ); } export default function Profile() { return ( <Avatar /> ); }
Las props que puedes utilizar con una etiqueta <img>
están predefinidas (ReactDOM se ajusta al estándar HTML). Sin embargo, puedes pasar cualquier prop a tus propios componentes, como <Avatar>
, para personalizarlos. ¡Aquí te mostramos cómo hacerlo!
Pasar props a un componente
En este código, el componente Profile
no está pasando ninguna prop a su componente hijo, Avatar
:
export default function Profile() {
return (
<Avatar />
);
}
Puedes pasar props al elemento Avatar
en dos pasos.
Paso 1: Pasar props al component hijo
Primero, pasa algunas props al elemento Avatar
. Por ejemplo, vamos a asignar dos props: person
(un objeto) y size
(un número):
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
Ahora puedes acceder a estas props dentro del componente Avatar
.
Paso 2: Acceder a props dentro del componente hijo
Puedes acceder a estas props especificando sus nombres person, size
separados por comas dentro de ({
y })
justo después de function Avatar
. Esto te permitirá utilizarlas dentro del código de Avatar
como si fueran variables.
function Avatar({ person, size }) {
// puedes acceder a los valores de person y size desde aquí
}
Agrega lógica a Avatar
que utilice las props person
y size
para la renderización, ¡y eso es todo!.
Ahora puedes configurar Avatar
para que se renderice de diferentes maneras con distintas props. ¡Prueba ajustando los valores!
import { getImageUrl } from './utils.js'; function Avatar({ person, size }) { return ( <img className="avatar" src={getImageUrl(person)} alt={person.name} width={size} height={size} /> ); } export default function Profile() { return ( <div> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> <Avatar size={80} person={{ name: 'Aklilu Lemma', imageId: 'OKS67lh' }} /> <Avatar size={50} person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} /> </div> ); }
Las props te permiten considerar de forma independiente los componentes padre e hijo. Por ejemplo, puedes modificar las props person
o size
dentro del componente Profile
sin preocuparte por cómo serán utilizadas por el componente Avatar
. De manera similar, puedes cambiar la forma en que Avatar
utiliza estas props sin necesidad de revisar el componente Profile
.
Considera las props como «controles» que puedes ajustar. Cumplen el mismo papel que los argumentos de una función—de hecho, ¡las props son el único argumento de tu componente! Las funciones de los componentes de React aceptan un único argumento, un objeto props
:
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
En general, no necesitas acceder al objeto completo de props
, por lo que puedes desestructurarlo en props individuales.
Asignar un valor predeterminado para una prop
Si quieres asignar un valor predeterminado para una prop en caso de que no se especifique ningún valor, puedes hacerlo mediante la desestructuración colocando =
seguido del valor predeterminado justo después del parámetro:
function Avatar({ person, size = 100 }) {
// ...
}
Ahora, si renderizas <Avatar person={...} />
sin la prop size
, el valor de size
se establecerá automáticamente en 100
.
El valor predeterminado sólo se utilizará si falta la prop size
o si se pasa size={undefined}
. Sin embargo, si se pasa size={null}
o size={0}
, el valor predeterminado no se aplicará.
Reenviar props con la sintaxis de propagación JSX
A veces, pasar props se vuelve muy repetitivo:
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
No hay ningún problema en tener código repetitivo—ya que puede ser más legible. Sin embargo, en ocasiones, es posible que prefieras ser más conciso. Algunos componentes reenvían todas sus props a sus hijos, como lo hace Profile
con Avatar
. Dado que no utilizan directamente ninguna de sus props, tiene sentido utilizar una sintaxis de «propagación» más concisa:
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
Esto permite reenviar todas las props de Profile
a Avatar
sin la necesidad de especificar cada una de ellas.
Recuerda utilizar la sintaxis de propagación con moderación. Si estás utilizando esta sintaxis en cada componente, es probable que algo no esté correctamente estructurado. En muchos casos, esto sugiere que deberías dividir tus componentes y pasar los hijos como elementos JSX separados. ¡Más información sobre esto a continuación!
Pasar JSX como hijos
Es común anidar etiquetas nativas del navegador:
<div>
<img />
</div>
En ocasiones, querrás anidar tus propios componentes de la misma forma:
<Card>
<Avatar />
</Card>
Al anidar contenido dentro de una etiqueta JSX, el componente padre recibirá ese contenido a través de una prop llamada children
. En el ejemplo a continuación, el componente Card
recibe una prop children
con el valor de <Avatar />
y lo renderiza dentro de un div contenedor:
import Avatar from './Avatar.js'; function Card({ children }) { return ( <div className="card"> {children} </div> ); } export default function Profile() { return ( <Card> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> </Card> ); }
Prueba cambiando <Avatar>
dentro de <Card>
con algún texto para ver cómo el componente Card
puede envolver cualquier contenido anidado. No es necesario que el componente «sepa» qué se está renderizando dentro de él. Este patrón flexible se puede observar en muchos casos.
Puedes imaginar un componente con una prop children
como si tuviera un «hueco» que puede ser «llenado» por sus componentes padres con JSX arbitrario. La prop children
suele utilizarse para crear envoltorios visuales como paneles, rejillas, etc.
Ilustrado por Rachel Lee Nabors
Cómo las props cambian con el tiempo
El componente Clock
que se muestra a continuación recibe dos props de su componente padre: color
y time
. (Se omite el código del componente padre porque utiliza estado, del cual no ahondaremos en este momento.)
Prueba cambiando el color en la lista desplegable que aparece a continuación:
export default function Clock({ color, time }) { return ( <h1 style={{ color: color }}> {time} </h1> ); }
Este ejemplo demuestra que un componente puede recibir props que cambian a lo largo del tiempo. ¡Las props no siempre son estáticas! Aquí, la prop time
cambia a cada segundo, y la prop color
cambia cuando se elige un color diferente. Las props reflejan los datos de un componente en cualquier momento, y no sólo al inicio.
Sin embargo, las props son inmutables—un término de la informática que significa «inalterable». Si un componente necesita cambiar sus props (por ejemplo, en respuesta a una interacción del usuario o nuevos datos), debe «solicitar» a su componente padre que le pase nuevas props—¡un nuevo objeto! Las props antiguas se descartarán y eventualmente el motor de JavaScript liberará la memoria que ocupaban.
No intentes «cambiar las props». Cuando necesites responder al input del usuario (como cambiar el color seleccionado), deberás «establecer un estado», lo cual puedes aprender en El estado: la memoria de un componente.
Recapitulación
- Para pasar props, simplemente agrégalas al JSX, de la misma forma en que lo harías con los atributos HTML.
- Para acceder a las props, utiliza la sintaxis de desestructuración
function Avatar({ person, size })
. - Puedes asignar un valor predeterminado como
size = 100
, que se utiliza para las props faltantes yundefined
. - Puedes reenviar todas las props con la sintaxis de propagación JSX
<Avatar {...props} />
, ¡pero no abuses de ella! - Todo JSX anidado como
<Card><Avatar /></Card>
aparecerá como la propchildren
del componenteCard
. - Las props son instantáneas de solo lectura en el tiempo: cada renderizado recibe una nueva versión de las props.
- No puedes cambiar las props. Si necesitas interactividad, tendrás que establecer un estado.
Desafío 1 de 3: Extraer un componente
Este componente Gallery
contiene un marcado muy similar para dos perfiles. Extrae un componente Profile
para reducir la duplicación. Tendrás que determinar qué props pasarle.
import { getImageUrl } from './utils.js'; export default function Gallery() { return ( <div> <h1>Científicos Notables</h1> <section className="profile"> <h2>Maria Skłodowska-Curie</h2> <img className="avatar" src={getImageUrl('szV5sdG')} alt="Maria Skłodowska-Curie" width={70} height={70} /> <ul> <li> <b>Profesión: </b> física y química </li> <li> <b>Premios: 4 </b> (Premio Nobel de Física, Premio Nobel de Química, Medalla Davy, Medalla Matteucci) </li> <li> <b>Descubrió: </b> polonio (elemento químico) </li> </ul> </section> <section className="profile"> <h2>Katsuko Saruhashi</h2> <img className="avatar" src={getImageUrl('YfeOqp2')} alt="Katsuko Saruhashi" width={70} height={70} /> <ul> <li> <b>Profesión: </b> geoquímica </li> <li> <b>Premios: 2 </b> (Premio Miyake de geoquímica, Premio Tanaka) </li> <li> <b>Descubrió: </b> un método para medir el dióxido de carbono en el agua de mar </li> </ul> </section> </div> ); }