Manejo avanzado de Children en React

Manejo avanzado de Children en React

Hola viajero, espero estés disfrutando tanto como yo este curso de React JS desde cero, ya que hoy, trataremos el tema de Children en React, un tema del que varios colegas ya han enseñado, no obstante, pretendo profundizar aun más en este tema, enseñándote la composición de componentes, si no, como puedes comunicar componentes a través del uso de Children.

Si te esta gustando mi curso, puedes apoyar suscribiéndote a mi canal y compartiendo en tus redes sociales.

 

📌 Suscríbete a mi canal y activa la campanita para que no te pierdas ningún video 🤘

 

¿Qué aprenderás de los Children?

  • ¿Qué son las Children?
  • Como agregarlas a un componente.
  • Tipos de Children que puedes pasar a un componente.
  • Filtrar y solo aceptar Children validas por la API de React.
  • Vamos a crear un ejemplo donde podrás ver en acción la composición de componentes y la comunicación entre ellos a través de Children.

 

 

Repositorio:

  • Puedes descargar el código de esta clase aquí.
  • O si lo deseas puedes clonar el repositorio y cambiarte a la rama "Children".

 

git clone https://github.com/EWebik/react-js.git
git checkout children

 

¿Qué son las Children en React?

Las Children son una forma de composición de componentes, donde, valga la redundancia, podemos pasar componentes a través de propiedades.

 

¿Cómo podemos agregar Children a un componente?

Esto se lleva acabo cuando escribimos un componente mediante el marcado de doble etiqueta, y entre su etiqueta de apertura y cierre, escribimos un componente hijo valido, por ejemplo:

<Padre>
    <Hijo1/>
    <Hijo2/>
</Padre>

Al hacer lo anterior, en las propiedades del componente <Padre /> aparece el atributo Children, el cual, contiene un array con la información de los dos componentes <Hijo1/> e <Hijo2 />.

Por lo tanto, en el componente <Padre /> podemos recuperar los hijos y montarlos directamente en la DOM.

class Padre extends React.Component{
        render(){
               const {children} = this.props;
               
               return(
                      <div className="padre">
                              <h1>{"Props Children by EWebik"}</h1>
                              <div className="hijos">
                                 {
                                   children
                                 }
                             </div>
                      </div>
               )
        }
}

En código anterior:

  1. Por destructuración obtenemos la propiedad children.
  2. Y en el return del componente agregamos una llaves y escribimos las children.
  3. Al hacer esto, React montara dicha propiedades como componentes en nuestra DOM.

Así de sencillo podemos utilizar este tipo de propiedades, no obstante, deseo profundizar más en el tema y te enseñare algunos temas un poco más avanzados, por ejemplo:

  • ¿Qué tipos de componentes podemos pasar en las Children.
  • ¿Cómo manipular y filtrar este tipo de propiedades?
  • Comunicación de componentes.

Comencemos con el primer punto.

 

Tipos de componentes validos en las Children

En esencia podemos pasar tipos como:

  • Componentes
  • Elementos como párrafos, div, headers (H2,H3,etc).
  • Textos
  • Expresiones de JavaScript como Templete Strings
  • Operaciones
  • Funciones
  • Etc.
<Padre>
    <Hijo1/>
    <p>Párrafo</p>
     Texto...
     <br/>
     {`Template String ${'Hola'}`}
     {()=>{}}
</Padre>

Nota: A pesar de que podemos pasar funciones en las Children, en React no se puede renderear una función, por lo tanto, en la consola del navegador verás un error. Para solucionar esto, deberás interceptar antes del render las propiedades Children y aplicar un filtro, ya se para separar dicha función, o eliminarla del render.

No te preocupes, en el apartado siguiente veremos como crear estos filtros y aprenderás a manipular las Children antes de ser montadas en la DOM.

 

¿Cómo manipular y filtrar Children?

Podemos realizar algunas acciones antes de montar las props Children en la DOM, a esto yo le llamo filtro, ya que eliminas aquellos componentes no validos y/o separas funciones que necesitas pero que no quieres que se monten en la DOM.

Para realizar esto hay varias opciones que puedes encontrar en la documentación oficial de React, aquí veremos dos funciones muy útiles y que aplicaremos más adelante en nuestro ejemplo.

 

API de alto nivel de React

Las siguientes funciones las encuentras el apartado de la API de alto nivel de React y que te serán muy útiles en tus proyectos.

 

React.Children.toArray

React.Children.toArray recibe como parámetro las propiedades children y forzamos a que las Children siempre sean un arreglo de objetos, esto es muy útil, ya que, si en las Children te pasan un solo item, la propiedad se comportara como un objeto o según el tipo de componente que se haya pasado.

Ahora, si se pasan más de un componente, la propiedad se comportara como un arreglo, por lo tanto, tendrías que identificar si es un arreglo o no y actuar en consecuencia.

En cualquier caso, al utilizar React.Children.toArray, siempre tendrás un array y así no te debes preocupar por el número de componentes que te pasen.

React.Children.toArray(children)

 

React.Children.map

React.Children.map es una excelente opción para manipular las Children antes de ser montadas, ya que, podemos decidir que hacer con cada componente que sea pasado en las propiedades.

React.Children.map(children, function[(thisArg)])

Esta función recibe dos parámetros:

  • Las propiedades children
  • Y una función callback donde regresará cada componente dentro de las propiedades

Entonces, con este comportamiento podemos discriminar por cada componente su comportamiento, y decidir, si se muestra o no.

Cabe mencionar que tanto React.Children.toArray y React.Children.map, solo regresan componentes validos, por ejemplo, si pasáramos una función como Children, estas funciones las filtrarían, por lo tanto, tendríamos que acceder a dicha función antes de pasarla a estas dos funciones para no perderla.

 

React.cloneElement()

React.cloneElement() es otra de las funciones con gran utilidad en React, ya que nos permite agregar propiedades a los Children antes de ser montados en la DOM.

React.cloneElement(
  element,
  [props],
  [...children]
)

Y no solo nos agrega propiedades, si bien, como su nombre indica, clona el componente de la Children y lo convierte en otro componente agregándole la información que le pasemos en las nuevas propiedades y esto sin que el componente pierda sus propiedades originales.

Quizá suene complicado pero si miras el vídeo, en el ejemplo, lo verás en acción y estoy seguro que se despejaran tus dudas.

 

Comunicación de componentes a través de Children

Excelente, ya conoces lo básico de las Children, ahora aplicaremos todo lo aprendido con un pequeño Chat entre componentes, vamos a comunicar tanto al componente padre como los componentes hijos sin el paso explicito de propiedades, además, lo haremos sin usar API Context o Redux.

Si no te queda claro el ejemplo, no olvides ver el vídeo, en el realizo el ejemplo paso a paso.

Formulario ejemplo del uso de las Children en React

Bien, comencemos a desarrollar el ejemplo paso a paso:

  1. Este es el archivo de estilos CSS con el cual harás la interfaz de usuario.
.padre{
  border: 1px solid #111;
  padding: 20px;
  text-align: center;
}
.hijos{
  display: flex;
  justify-content: center;
  align-items: center;
}
.hijo{
  border: 1px solid #111;
  padding: 5px;
  text-align: center;
  margin: 10px;
}

Como puedes ver son bastante simples, solo es acomodarlos un poco y ponerles un borde.

  1. Como segundo paso vamos a crear los componentes que serán pasados como Children, "<Child1 />" y "<Child2 />".

 

const Child1 = (props)=>{
  return(
    <div className="hijo">
       <h2>{"Hijo 1"}</h2>
       <p>{props.componente + " " + props.mensaje}</p>
        <textarea rows="5" onChange={(e)=>{
          props.actualizarState(e.target.value, "Hijo 1 dice:")
        }} />
    </div>
   
  )
}

 

const Child2 = (props)=>{
  return(
    <div className="hijo">
      <h2>{"Hijo 2"}</h2>
      <p>{props.componente + " " + props.mensaje}</p>
        <textarea rows="5" onChange={(e)=>{
          props.actualizarState(e.target.value, "Hijo 2 dice:")
        }} />
  </div>
  )
}

 

Tanto "Child1" como "Child2", tienen el mismo código y funcionamiento:

  • A ambos los envuelve un div con un className igual a hijo.
  • Tiene un header H2 con el nombre del componente.
  • Un párrafo P que imprimirá que componente esta escribiendo y el mensaje que esta enviando.
  • Finalmente cuenta con un textarea, donde el usuario podrá ingresar el mensaje que desea enviar.

No obstante, lo más importante en estos componentes es que reciben las props:

  • componente: Con esta propiedad sabremos quien esta escribiendo
  • mensaje: Almacena el mensaje que ingresa el usuario
  • actualizarState: Con esto actualizaremos el state del componente padre.

Con estas tres propiedades haremos toda la magia, ya que las actualizaremos desde el state del componente padre, tal y como veremos a continuación.

 

  1. Ahora desarrollemos el componente padre que recibirá los Children.
class Padre extends React.Component{
  constructor(props){
    super(props);
    this.state={
      mensaje:"",
      componente:""
    }
  }

  actualizarState = (mensaje, componente)=>{
    this.setState({mensaje, componente})
  }

  render(){
    const {children: propsChildren} = this.props;
    
    //Siempre manejes children como array
    //Comunicación de componentes aplicando Children
    let children = React.Children.map(propsChildren,(child, index)=>{
      return React.cloneElement(child,{
        mensaje: this.state.mensaje,
        componente: this.state.componente,
        actualizarState: this.actualizarState,
      });
    })

    
    return(
      <div className="padre">
        <h1>{"Props Children by EWebik"}</h1>
      <p>{this.state.componente + " " + this.state.mensaje}</p>
      <textarea rows="5" onChange={(e)=>{
        this.actualizarState(e.target.value, "Padre dice:")
      }} />
      <div className="hijos">
        {
          children
        }
      </div>
       
      </div >
    )
  }
}

 

Tanto la parte del state como la actualización del state ya la hemos visto en otras clases, así que no me detendré en esto, te dejo aquí la clase del state por si deseas hacer un repaso:

 

Comprendiendo el State y Ciclo de vida de los componentes en REACT JS

Comprendiendo el State y Ciclo de vida de los comp...

Comprender 🤔 el 【▷ State y Lifecycle ◁】 te permit...

 

Por el momento me centraré en la parte del filtro que es lo que realmente importa para esta clase:

const {children: propsChildren} = this.props;
    
    //Siempre manejes children como array
    //Comunicación de componentes aplicando Children
    let children = React.Children.map(propsChildren,(child, index)=>{
      return React.cloneElement(child,{
        mensaje: this.state.mensaje,
        componente: this.state.componente,
        actualizarState: this.actualizarState,
      });
    })

Del código anterior podemos explicar lo siguiente:

  • En primer lugar obtenemos las children por destructuración y las renombramos a "propsChildren".
  • Ahora utilizaremos una de las funciones que ya te explique anteriormente "map", con esta función recorremos cada uno de los componentes pasados en las children y le agregaremos las propiedades que serán afectadas por el state del componente "padre".
  • Con React.cloneElement crearemos un componente nuevo que tendrá todas las propiedades de cada child, pero, agregaremos las propiedades:
    • componente
    • mensaje
    • Y actualizarState

Como puedes observar, no solo filtramos las Children, si no que las convertimos en nuevo componente conectando al componente padre.

 

  1. Por último, montamos el componente Padre en el render y visualizamos en el navegador la salida.
ReactDOM.render(
  <Padre>
    <Child1/>
    <Child2/>
  </Padre>,
  document.getElementById('root')
);

 

Y listo, ya tienes un pequeño Chat entre componentes, donde lo importante es que has comunicado, tanto Padre a hijos como hijo a hijo.

Este ejemplo es un uso avanzado de Children y composición de componentes, pero lo más importante es que es otra manera en que puedes comunicar tus componentes sin usar API Contex u otras librerías como Redux.

Bien amigos, llegamos al final espero que les haya gustado y compartan este post, nos vemos en la siguiente clase.

 


Juan Carlos G

Electrónica y diseño web

Durante años he desarrollado plataformas dedicadas al rastreo satelital y varios sitios web que se encuentran en la primera página de Google, y hoy quiero compartir contigo lo que se en tecnologías como Node JS, PHP, C# y Bases de datos, si quieres apoyarme sígueme en mis redes sociales y suscríbete a mi canal de YouTube.

Puedes seguirme en mis redes