No me funcionaba el ReactDOM.createPortal, buscando en la documentación de React me indicaba que se escribe diferente, cabe aclarar que es la versión 18:
Introducción y requisitos
¿Qué necesitas para aprender React.js?
Maquetación con React.js
¿Qué es un componente?
Componentes de TODO Machine
¿Cómo se comunican los componentes? Props y atributos
Estilos CSS en React
Interacción con React.js
Eventos en React: onClick, onChange
¿Qué es el estado?
Contando TODOs
Buscando TODOs
Completando y eliminando TODOs
Librería de Iconos Personalizados
Iconos en React: librerías y SVG
Iconos con colores dinámicos
Herramientas avanzadas: escalabilidad, organización y persistencia
Local Storage con React.js
Custom Hooks
Organización de archivos y carpetas
Feature-First Directories en React
Tips para naming y abstracción de componentes React
¿Qué son los efectos en React?
Estados de carga y error
Actualizando estados desde useEffect
Reto: loading skeletons
¿Qué es React Context?
useContext
¿Qué son los React Portals?
Reto: estados para abrir y cerrar un modal
Maquetando formularios en React
Crear TODOs: React Context dentro de React Portals
Deploy
Despliegue de TODO Machine en GitHub Pages
Presentación de proyectos para tu portafolio
Próximos pasos: React #UnderTheHood
Diferencias entre versiones de React.js
¿Cuándo realmente necesitas React.js?
Bonus: creando proyectos en React desde cero
React con Create React App
React con Next.js
React con Vite
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
No se trata de lo que quieres comprar, sino de quién quieres ser. Aprovecha el precio especial.
Antes: $249
Paga en 4 cuotas sin intereses
Termina en:
Juan David Castro Gallego
Aportes 29
Preguntas 8
No me funcionaba el ReactDOM.createPortal, buscando en la documentación de React me indicaba que se escribe diferente, cabe aclarar que es la versión 18:
Esa técnica con las manos para abrir portales me parece conocida! 🤣
Lo que hice para abrir y cerrar el Modal fue pasarle el contexto al componenete createTodoButton y al hacerle click que cambie su estado de false a true y a la inversa:
function CreateTodoButton() {
const {
setOpenModal,
openModal,
} = React.useContext(TodoContext)
return (
<button
className={"newTodo"}
onClick={() => {setOpenModal(!openModal)}}
>
<FaPlus
className="icon"
/>
</button>
);
}
¿Para qué sirven los portales?
Los portales nos permiten ubicar un componente hijo dentro del conjunto de componentes que se renderizan en el nodo html principal del DOM, generalmente el id = “root”, pero hacer que aparezcan en un **nodo **fuera de la jerarquía del DOM. Esto permite una mayor facilidad a la hora de maquetar y estilizar componentes que aparecen y desaparecen en el renderizado de nuestra página como los modales (ventanas).
Gracias a los portales, por ejemplo, podemos ubicar a nuestro componente <Modal> luego del conjunto de componentes que tenemos en la AppUI como <TodoCounter/>, <TodoSearch/> o <CreateTodoButton/>, pero el renderizado se hará en el div del nodo html que nosotros indiquemos, osea fuera del “root”. Esto trae como ventaja por ejemplo poder estilizar fácilmente el modal para que aparezca por encima del resto de componentes.
Mi solución fue un if en el componente de button usando el contexto.
Aquí esta la documentación más reciente de la API del DOM createPortal.
Según lo que entendí, es así.
Se siente mucho más ordenado usando useContext, ¡gran clase JuanDC!
createPortal recibe 3 parametros:
Aquí tienen esta página por si les interesa no tener que hacer un modal desde el principio, sino usar los que ofrece bootstrap https://react-bootstrap.netlify.app/docs/components/modal/.
Seria algo asi, si se finjan tego declarado mi useState en false como dijo el profesor porque quiero que mi modal desde el principio este cerrado, luego en mi etiqueta de button, con el manejador de onClick hago que el estado cambie a true y como la condicion abajo dice cada vez que openModal sea verdadero muestrame ese componente. Cabe resaltar que en mi componente de modal tengo un boton llamado closeModal el cual cuando quiero cerrar el modal lo actualizo a false y este completa la accion.
const [openModal, setOpenModal] = useState(false);
<button className={styles.btn} onClick={() => setOpenModal(true)}>
<div></div>
<div></div>
<div></div>
</button>
{openModal ? <Modal closeModal={() => setOpenModal(false)} />
Les comparto la documentación: createPortal
Otra manera de hacerlo es con la importación directa de createPortal sin utilizar ReactDOM
import React from 'react'
import { createPortal } from 'react-dom'
export const ModalMessage = ( {children}) => {
return (
createPortal(
<div>
{children}
</div>,
document.body
)
)
}
No me renderizaba el portal en la consola, para esto realicé la importacion de createPortal de esta manera:
import React from "react";
import { createPortal } from "react-dom";
function Modal({ children }) {
return createPortal(
<div className="Modal">
{children}
</div>,
document.getElementById('modal')
);
}
export { Modal };
Por otra parte para que abrir y cerrar el portal con el createButton hice el siguiente codigo:
import React from 'react';
import './CreatTodoButton.css';
import { TodoContext } from '../TodoContext';
function CreateTodoButton() {
const {
openModal,
setOpenModal,
} = React.useContext(TodoContext);
return(
<button
className="CreateTodoButton"
onClick={
(e) =>
{setOpenModal(!openModal)}
}>+</button>
)
};
No sabia de esta funcionalidad, genial genial!
Yo lo hice de esta manera, desde AppUI.
{openModal && createPortal(
<ModalNewTodo openModal={openModal} />,
document.body
)}
Con MUI
export const ModalNewTodo = ( ) => {
const {searchValue,setSearchValue,openModal, setOpenModal} = useContext(TodoContext);
const [tareaValue, setTarea] = useState(searchValue);
const handleCancel = () => {
setOpenModal(!openModal);
setSearchValue(’’);
}
const handleAccept = () => {
setOpenModal(!openModal);
}
return (
<>
<Dialog open={openModal} onClose={handleCancel} fullWidth>
<DialogTitle>Nueva tarea</DialogTitle>
<DialogContent>
<DialogContentText>
{searchValue ? ’ ¿Está seguro que quiere registar esta tarea?’ : ’ Escribe la tarea que deseas realizar’}
</DialogContentText>
<TextField
autofocus
margin="dense"
id="txt_tarea"
label="Descripción"
type="text"
fullWidth
variant="standard"
value={tareaValue}
onChange={(event) => {
setTarea(event.target.value);
}}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleCancel}>Cancelar</Button>
<Button onClick={handleAccept}>Aceptar</Button>
</DialogActions>
</Dialog>
</>
)
}
Button
export const CreateTodoButton = () => {
const {setOpenModal,openModal} = useContext(TodoContext);
const handleClickAdd = () =>{
setOpenModal(!openModal);
}
return (
<Stack sx={{width:100, mt:1}}>
<Button variant=“contained” startIcon={<AddIcon />} size=“small” onClick={handleClickAdd}>Agregar</Button>
</Stack>
)
}
Referencia createPortal
Juan sos el mejor profe del mundo!
Una consulta, si va a haber un formulario, no seria mejor dentro del mismo agregar dos botones, uno para que al guardar se cierre el modal y otro boton para cerrar el modal en el caso de que no quieran agregar todos, sino lo presionen por error?
estoy pensando en hacer el reto asi
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?