19

¿Qué son los React Portals? Teletransportación de componentes en React.js

49072Puntos

hace 2 años

Los React Portals permiten que algunos componentes salgan del flujo o estructura por defecto de nuestra aplicación. Con ellos podemos crear portales para teletransportar componentes entre diferentes nodos de HTML. Los componentes vivirán en lugares diferentes de la página, lo que evitará muchos problemas de CSS (como z-index y overflow), pero React seguirá manteniendo control sobre ellos para comunicarles props y estados.

Con el siguiente gráfico te quedará más claro:

DOM nodes
react components

Características de React Portals

  • Se mantiene el control de React:

No importa que el portal se encuentre en un nodo del DOM diferente al de la App, características como el event propagation no cambiará y podrás usar a React junto con sus utilidades (manejo de ciclo de vida, context, estado), ya que este lo contempla como un componente más.

  • Son montados en un nodo diferente al de la App inicial:

Nuestro punto de entrada que por lo general es un index.js se mantendrá igual.

// index.jsximport React from'react';
import ReactDOM from'react-dom';
import App from'./App';

const rootElement = document.getElementById('app');
const root = ReactDom.createRoot(rootElement);

root.render(<App />);

Pero la magia sucede dentro de App, donde vamos a importar nuestro portal creado con la siguiente utilidad de ReactDOM: ReactDOM.createPortal(componente, nodo)

// App.jsxconst App = () = (
	  ...
	<Portal user="Platzinauta" />
)

const Portal = ({ user }) => {
  ReactDOM.createPortal(
    <div><p>Hi {user}</p></div>,
    document.getElmentById("modal")
  )
}

¿Cómo usar React Portals? 🚪

Ya tienes todo el contexto necesario para trabajar con React Portals, ahora vamos a ponerlos en practica con un ejemplo practico.

Vamos a crear una app que cuente los clicks que hacemos sobre un botón, pero lo haremos con un portal mientras que vamos a tener otro portal que se va a disparar una vez que hayamos hecho una determinada cantidad de clicks sobre el botón.

1️⃣ Crea las etiquetas de app, modal y advice

Como te lo mencione antes, cada portal funciona en un nodo diferente dentro nuestro HTML por lo que es necesario que tengas estas 3 etiquetas desde el inicio:

<body><divid="app" ></div><divid="modal"></div><divid="advice"></div></body>

2️⃣ Crea la estructura inicial de tu archivo App.jsx

Dentro de nuestra App vamos a tener el estado inicial y el botón que será el cual se encargue de aumentar el valor del mismo:

// App.jsxconst App = () => {
  const [clicks, setClicks] = React.useState(0)
  
  return(
    <divclassName="container" ><buttonclassName="appButton"type="button"onClick={() => setClicks(clicks + 1)}>
	        Click me!
        </button></div>  
  )
}

3️⃣ Crea tus portales para modal y advice

Nuestro modal se va a encargar de mostrar los clicks que ha hecho el usuario sobre el botón que se encuentra en al App, por lo que le debemos pasar el estado para que pueda hacer esto:

// modal.jsxconst Modal = ({ clicks }) => {
  return ReactDOM.createPortal(
    <divclassName="counter" ><h1>Clicks account</h1><p>You click the button {clicks} times</p></div>,
    document.getElementById("modal")
  )
}

Por otro lado, nuestro componente advice va a recibir los siguientes parámetros:

  • clicks: el número de clicks que hizo el usuario hasta antes de que se mostrara
  • setClicks: la función que hace el set del estado para que este pueda reiniciar
  • message: también podrá recibir un mensaje personalizado para mostrar
// advice.jsxconst Advice = ({ clicks, setClicks, message }) => {
  return ReactDOM.createPortal(
    <divclassName="container-advice"><divclassName="advice"><h2>{message}</h2><p>You clicked {clicks} times</p><buttontype="button"onClick={() => setClicks(0)} >Restart</button></div></div>,
    document.getElementById("advice")
  )
}

4️⃣ Inserta los portales a tu App.jsx

Ya tenemos casi todo, recuerda que los portales por si solos no estarán en nuestra App, sino que debemos importarlos para que puedan funcionar y ser mostrados

En este punto ya podremos agregar una condición para mostrar advice que va a reiniciar la cuenta a 0 y automáticamente desaparecerá, mientras que nuestro Modal solo le deberemos pasar el estado de los clicks de la siguiente manera

const App = () => {
  const [clicks, setClicks] = React.useState(0)
  
  return(
    <div className="container" >
        <button 
        className="appButton" 
        type="button" 
        onClick={() => setClicks(clicks + 1)}>
	        Click me!
        </button>
        <Modal clicks={clicks} />
        {clicks === 10 && 
	        <Advice click={clicks} 
	        setState={setClicks} message="You cracked the button :(" />
        }
    </div>  
  )
}

En este codepen podrás ver la demo e interactuar con ella.

Con este ejercicio básico, aprendiste que no importa que los portales existan en otra parte distinta del DOM, con React siempre tendrás una conexión para compartir estados y ciclos de vida.

¿Qué otros usos le ves a los React Portals?

En este pequeño post vimos el uso común de crear un modal y un mensaje flotante que indican el estado de nuestra aplicación, sería interesante el recrear un juego como Portal con esta utilidad ¿No crees?, obviamente tendríamos nuestras limitantes pero sería un reto enorme 👀.

  • Menus
  • Modals
  • Loaders
  • Dialog boxes

¿Qué más se te ocurre?

Te dejo aquí una colección de cursos para puedas tener un mejor dominio sobre él:

#NuncaParesDeAprender

Leonardo de los angeles
Leonardo de los angeles
LeoCode0

49072Puntos

hace 2 años

Todas sus entradas
Escribe tu comentario
+ 2
5
33399Puntos

Excelente post, Leo. Y gracias por las sugerencias de cursos.

5
24895Puntos

Muchas gracias maestro por compartir este blog, lo complementare con el reto de Web Developer 😃