Componentes con Hijos Personalizables en React
En el artículo anterior creamos Header
e hicimos que renderice Hello
internamente. Hoy vamos a hacer que el contenido de Header
se pueda personalizar como un prop de forma que podamos decidir si usar Hello
o no.
Esto además nos va a evitar el uso de prop drilling, pero ¿Por qué querríamos evitar esto? En nuestro caso no hay ningún problema con usar prop drilling, pero a medida que agregemos más y más componentes que reciban y pasen props a sus hijos esto se puede llegar a volver un problema debido a que:
- Complicaría refactorizar nuestros datos (props).
- Terminaríamos pasando más props de los necesarios para evitar problemas de olvidarnos un prop.
- No pasaríamos props que si son necesarios debido al abuso de
defaultProps
. - Dificultaría seguir el flujo de props en nuestra aplicación si terminamos renombrando props a mitad de camino.
Todo esto se puede evitar haciendo lo que vamos a hacer eso.
function Header(props) {
return React.createElement(
"header",
null,
React.createElement(Hello, { name: props.name })
);
}
Header.propTypes = {
name: PropTypes.string
};
Header.defaultProps = {
name: "Mundo"
};
Ese es nuestro Header
, vamos a hacer que en vez de recibir el prop name
reciba un prop que vamos a llamar children
y vamos a hacerlo obligatorio.
function Header(props) {
return React.createElement("header", null, props.children);
}
Header.propTypes = {
children: PropTypes.node.isRequired
};
Como vemos pasamos props.children
como tercer elemento de React.createElement
, esto es porque el contenido, como lo definimos en nuestros propTypes, es un nodo de React por lo que es cualquier cosa que sirva como hijo de un elemento.
Si actualizamos el ejemplo usando nuestro nuevo Header
quedaría así:
function Hello(props) {
return React.createElement("h1", null, `Hola ${props.name}!`);
}
Hello.propTypes = {
name: PropTypes.string
};
Hello.defaultProps = {
name: "Mundo"
};
function Header(props) {
return React.createElement("header", null, props.children);
}
Header.propTypes = {
children: PropTypes.node.isRequired
};
const element = React.createElement(Header, {
children: React.createElement(Hello, { name: "Sergio" })
});
const node = document.getElementById("app");
ReactDOM.render(element, node);
Como vemos ahora Header
no sabe que Hello
recibe un prop name
, el solo recibe el elemento creado a partir de Hello
como su prop children
y lo coloca dentro de <header>
.
Con esto acabamos de mejorar como nuestro componente se combine de otros componentes lo que permitiría que Header reciba cualquier otro componente o elemento de React y lo envuelva en la etiqueta <header>
.
En el siguiente artículo vamos a ver más sobre este prop children