Las propiedades son la forma que tiene React para pasar parámetros de un componente padre a los hijos.normal que un componente pase datos a los componentes hijos, sin embargo, no es lo único que se puede pasar, si no que existe ocasiones en las que los padres mandar funciones a los hijos, para que estos ejecuten operaciones de los padres, puede sonar extraño, pero ya veremos cómo funciona.
Los props se envían a los componentes al momento de crearlos, y es tan fácil como mandar las propiedades como un atributo del <tag> del componente, por ejemplo, supongamos que tenemos un componente <ItemList> , el cual necesita recibir los datos de un producto, dicho producto debe contener el nombre y un precio:
<ItemList product={item}/>
Mandar objetos es una forma simple y limpia de mandar propiedades, pero también lo podríamos hacer en varias propiedades, por ejemplo:
<ItemList productName={product.name} productPrice={product.price}/>
La única diferencia entre estos dos métodos será la forma de recuperar las propiedades. Para recuperar una propiedad es necesario usar el prefijo, this.props , por lo que en el primer ejemplo, el ítem se recupera como this.props.product , y en el segundo ejemplo, sería this.props.productName para el nombre y this.props.productPrice para el precio.
Una limitación que tenemos para mandar props, es la de no utilizar un nombre de propiedad que coincida con los atributo de React, por ejemplo: onClick , onChange , className , etc.
Las propiedades son inmutables
La propiedad tiene la característica de ser inmutables, es decir, no debemos de modificarlas o actualizarlas, pues es considerada una mala práctica, solo las debemos utilizar de modo lectura.
Regresemos al ejemplo del formulario que vimos en la sección de componentes con estado y sin estado del que hablamos en un artículo pasado. En este ejemplo, creamos el componente App y sobre este montamos un formulario de registro de empleados. Ahora bien, ¿qué pasaría si quisiéramos que la acción de guardar la controlara el componente padre? La solución es simple, el componente padre tendría que enviar como props la función de guardar, para que el hijo la ejecute.
Lo primero será pasar el formulario a un componente externo, por lo cual, crearemos un componente llamado EmployeeForm , el cual se verá como a continuación:
import React from 'react' class EmployeeForm extends React.Component{ constructor(){ super(...arguments) this.state = { firstName: '', lastName: '', age: '' } } componentDidMount(){ this.refs.firstName.focus(); } handleChanges(e){ let newState = Object.assign( this.state, {[e.target.id]: e.target.value}) this.setState(newState) } saveEmployee(e){ this.props.save(this.state) } render(){ return ( <form> <label htmlFor='firstName'>Nombre</label> <input ref='firstName' id='firstName' type='text' value={this.state.firstName} onChange={this.handleChanges.bind(this)}/> <br/> <label htmlFor='lastName'>Apellido</label> <input id='lastName' type='text' value={this.state.lastName} onChange={this.handleChanges.bind(this)}/> <br/> <label htmlFor='age'>Edad</label> <input id='age' type='number' value={this.state.age} onChange={this.handleChanges.bind(this)}/> <br/> <button onClick={this.saveEmployee.bind(this)}>Guardar</button> </form> ) } } export default EmployeeForm
Este componente tiene dos cosas a resaltar, lo primero es que agregamos un botón (línea 44), el cual, al ser presionado, ejecutar la función saveEmployee declarada en este mismo componente, lo segundo es la función saveEmployee que declaramos en la línea 24, la cual ejecuta la función save enviada por el parent como prop.
Por otra parte, tenemos al componente App que será el padre del componente anterior:
import React from 'react' import { render } from 'react-dom' import EmployeeForm from './EmployeeForm' class App extends React.Component{ save(employee){ alert(JSON.stringify(employee)) } render(){ return ( <EmployeeForm save={ this.save.bind(this) }/> ) } } render(<App/>, document.getElementById('root'));
Podemos ver que al momento de crear el componente EmployeeForm , este le envía como una prop la función save . De esta forma, cuando el componente EmployeeForm , ejecute la propiedad, se lanzará una alerta con los datos capturados (línea 8).
Cuando es necesario “bindear” una función con una prop o queremos utilizar una función en un evento como onClick , onChange , etc. es necesario siempre empezar con this , y finalizar con binding(this) como se ve a continuación this.<function>.bind(this) .
Debido a que un componente padre puede enviar cualquier propiedad a sus componentes hijos, React proporciona un mecanismo para validar las propiedades que espera un determinado componente, validar su estructura, tipo de dato y definir un valor por default, para eso existen dos términos llamados PropTypes y DefaultProps, de los cuales estaremos hablando en otra ocasión.
Conclusiones
Como hemos visto, las propiedades son el único método que ofrece React para transmitir información de forma descendente, desde un componente padre hacia sus hijos, sin embargo, existe otras alternativas como Redux, una librería que permite gestionar la información de la aplicación totalmente desacoplada de los componentes.