No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de React.js

Curso de React.js

Juan David Castro Gallego

Juan David Castro Gallego

Reto: estados para abrir y cerrar un modal

25/34
Recursos

¿Cómo solucionar el reto anterior?

Para abordar el desafío del cierre y apertura del modal en la aplicación, es crucial comprender el proceso de revisión y comparación de cambios en el código. Utilizar herramientas como git puede ser de gran ayuda. En cada clase se ha creado un commit por cada experimento o parte de la aplicación construida, lo cual facilita esta revisión.

¿Qué cambios importantes se realizaron en el componente CreateToDoButton?

En el componente CreateToDoButton, se ha implementado un enfoque inteligente para su funcionalidad. Originalmente, este componente no tenía propiedades, pero con el reto, se integró la propiedad setOpenModal. Este ajuste permite manejar el estado del modal de manera eficaz:

  • Implementación de Z Index: Se agregó un z-index de 1 al CSS del CreateToDoButton. Esto asegura que el botón sea visible por encima de otros elementos en la interfaz del usuario, manteniendo su funcionalidad accesible en todo momento.

¿Cómo se actualiza el estado con una función?

La solución al reto implica una técnica más avanzada para manejar el estado en React. En lugar de enviar un valor booleano fijo (true o false) al actualizador del estado, se emplea una función de flecha que toma el estado anterior y devuelve su negación. Este enfoque optimiza la actualización del estado basándose en el estado anterior:

setOpenModal((state) => !state);

Este método no solo es elegante, sino también muy eficiente, permitiendo que el modal se abra y cierre de manera alternada según su estado actual.

¿Cuáles son las mejoras en el diseño del modal?

Al final se opta por una clase CSS llamada modal-background para estilizar adecuadamente el modal. Esta clase evita confusiones con el nodo HTML modal y contiene las siguientes propiedades para mejorar la UX:

  • Color de fondo traslúcido: Un fondo semi-transparente le da un aire moderno y limpio al modal.
  • Display Flex: Esto asegura que el contenido dentro del modal esté perfectamente centrado.
  • Ocupar todo el espacio: La configuración de modal-background permite cubrir el área necesaria para que el modal se destaque correctamente.

Al seguir estos pasos, al interactuar con el botón "crear nuevo todo", el modal se despliega de forma centrada y clara, mejorando la experiencia del usuario.

¿Qué resultado se obtiene al aplicar estos cambios?

La aplicación, que inicialmente está vacía, presenta un comportamiento dinámico al interactuar con el botón. Con el modal posicionado correctamente y visible gracias al z-index, se puede verificar que:

  • El modal se despliega de manera central, bien definido y con un efecto visual agradable.
  • El botón sigue siendo accesible y no se pierde debajo del modal, permitiendo cerrarlo de nuevo sin problemas.

Con estos cambios, la implementación del reto se realizó con éxito, mostrando cómo un diseño y manejo del estado más sofisticado pueden transformar la interfaz de usuario. Continúa explorando estas técnicas para fortalecer tu habilidad en React y proporcionar aplicaciones más dinámicas e intuitivas.

Aportes 23

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Solo agregue una **función, para negar el estado actual y asignarlo al botón de agregar en el OnClick **

 const abrirModal = () => {
        setOpenModal(!openModal);
      }

y utilice el ** context global ** para el estado.

const {openModal, setOpenModal} = React.useContext(TodoContext);<code> 

Código completo:

import { TodoContext } from '../TodoContext';
import React from 'react';
import './CreateTodoButton.css';

function CreateTodoButton(){
    const {openModal, setOpenModal} = React.useContext(TodoContext);
    
    const abrirModal = () => {
        setOpenModal(!openModal);
      }


    return (        
        <div className=''>
            <div className='d-flex flex-row justify-content-center'>
                <p>
                    <span className="inputColor">
                        <input type="text" placeholder="Ingresa alguna tarea..."/>
                        <span></span>	
                    </span>
                </p>        
            </div>
            <div className='d-flex flex-row justify-content-center'>
                <div className="box-2">
                    <div className="btn btn-two" onClick={abrirModal}>
                        <span>Agregar Tarea</span>
                    </div>
                </div>
            </div>
        </div>
    );
}

export {CreateTodoButton};

Les comparto como me quedo antes y despues de dar click al CreateTodoButton. Recibo sugerencias y recomendaciones, nunca antes habia creado un modal ni mucho menos agregarle overlay.
.
Antes de abrirlo:

.
Despues de abrirlo:

Yo lo pense un poco diferente utilizando lo que ya vimos en clases anteriores.

En el archivo TodoContext/index.js cree un nuevo estado y una funcion para cambiar ese estado y la inclui en el return del Toco Context:

const [openModal, setOpenModal] = React.useState(false);

const toggleModal = () => {
	setOpenModal(!openModal)
}

    return (
        <TodoContext.Provider value={{
            loading,
            error,
            completedTodos,
            totalTodos,
            searchValue,
            setSearchValue,
            searchedTodos,
            completeTodo,
            delteTodo,
            openModal,
            setOpenModal,
            toggleModal
        }}>
            {children}
        </TodoContext.Provider>
    );

Dentro del archivo CreateButton/index.js hice lo siguiente:

import React from 'react';
import './CreateTodoButton.css';
import { TodoContext } from '../TodoContext';

function CreateTodoButton() {
    const {
        toggleModal
    } = React.useContext(TodoContext)

    return (
        <button 
            className='CreateTodoButton'
            onClick={(event) => {
                toggleModal()
            }}
        >+</button>
    );
}

export {CreateTodoButton};

Pueden usar un useEffect para identificar la tecla de ESC y cerrar el modal con el teclado

<code> React.useEffect(() => {
        const close = (e) => {
          if(e.keyCode === 27){
            setOpenModal(false);
          }
        }
        window.addEventListener('keydown', close)
      return () => window.removeEventListener('keydown', close)
    },[]);
Gente, recuerden importar sus estilos una vez los creen, para que no se pasen rato buscando un supuesto error que no existe, donde los estilos no se perciben pero es solo que uno no ha importado el css. 😂😂

Así se ve mi modal.
Y me parece genial idea la función

onClick={() => setOpenModal(state => !state)}
Yo lo que hice fué exportar el estado setOpenModal y lo usé al momento de hacer click en el componente CreateTodoButton `import { Context } from '@context';import { useContext } from 'react'` `const Create_Todo_Button = () => {  const { openModal, setOpenModal } = useContext(Context)  return (   
      <button        className="text-3xl bg-blue-600 p-4 rounded-full text-white "        onClick={() => setOpenModal(!openModal) }      >        <FiPlus />      </button>   
  );}` `export default Create_Todo_Button;`
Así va quedando, creo que luego le encontraré otra funcionalidad al Modal porque yo quiero que las tareas se agreguen desde la misma barra de texto de ahí 😂 ![]()![](https://i.postimg.cc/vZGPYTH9/demo-modal-app.gif)
Comparto mi solución al reto, algo más larga que lo que vimos en esta clase, hice un función donde tenemos el contexto con la lógica, toggleTodo() que cambia el estado y agrega/quita una clase de css para que abra/cierre el modal. Agregué unos elementos al modal para ir dando estructura sin diseño aún y con los botones de crear (sin funcionar) y cerrar (funcionando). Saludos. repo: <https://github.com/mrivero40/multitask> ![](https://static.platzi.com/media/user_upload/imagen-c3b2047a-f1f4-47f9-8a89-018c37395ca3.jpg)

Lo que yo hice fue usar el contexto en el TodoButton, no sé si será la mejor opción pero me funciona para abrir y cerrarlo

import './CreateTodoButton.css';
import { TodoContext } from '../TodoContext';
import React from 'react';

function CreateTodoButton() {
    const {openModal, 
        setOpenModal,
       } = React.useContext(TodoContext)
    return(
        
        <button onClick={()=>{
            !openModal?
            setOpenModal(true):
            setOpenModal(false)
            
        }}>+</button>
    )
}

export {CreateTodoButton}

Yo dejé el open modal como setOpenModal(true) directamente, pues el botón create todo button nunca va a cerrarlo, para eso es el botón de cerrar del modal, entonces no lo vi necesario

Mi solución fue, envíar el estado del modal al CreateTodoButton

Y en el onClick del botón, solo hice que cambiará el estado dependiendo del valor que contenía

Mi solucion al Reto fue la siguiente:
Envio a la funcion el setOpenModal y en el onClick lo utilizo para negar el openModal, enviandolo como argumento y devolviendo su valor negado.

function CreateToDoButton({setOpenModal}){
    return(
        <button className="bg-gray-700 text-white rounded-lg p-2 mt-10"
            onClick={
            () => {
                setOpenModal(openModal => !openModal)
            }} 
        >Add a New ToDo</button>
    )
}
export default CreateToDoButton;

Esta fue mi solucion para el reto del button !!

    return (
        <button onClick={(event) => {
            openModal ? 
            setOpenModal(false) :
            setOpenModal(true) 

            console.log('escuchando')
        }}>
            +
        </button>
    );

No necesito un modal, ya que ya le había hecho una función createTodo

//Función
    const { item: todos,
        loadingStatus: todoStatus,
        saveItem: saveTodos
    } = useLocalStorage({ itemName: "TODOS-HACERES-V1", initialValue: [] });

    const createTodo = (text) => {
        if (text) {
            const timestamp = new Date().getTime();
            const newTodo = { id: timestamp, text, completed: false };
            saveTodos([...todos, newTodo]);
        }
    };

//Componente
function CreateTodobutton({
    inputCreateValue,
    setInputCreateValue,
    createTodo,
    totalTodos,
    todoStatus }) {

    function CreateButton() {
        createTodo(inputCreateValue)
        setInputCreateValue("");
    }
    if (todoStatus === "Ready") 
    return (
        <li className="CreateTodoButton">
            <input
                value={inputCreateValue}
                placeholder={totalTodos === 0 ? "Escribe una nueva tarea aqui" : ""}
                onChange={(event) => {
                    setInputCreateValue(event.target.value);
                }}
            />
            <BsPlus className="IconCreateTodo" onClick={CreateButton} />
        </li>
    );
}

`<CreateTodoButton setOpenModal={setOpenModal} />` es un componente en React que se utiliza para crear un botón que, al hacer clic, abre o cierra un modal. La propiedad `setOpenModal` es una función que actualiza el estado del modal. En este caso, se está pasando como prop para controlar si el modal está visible o no, utilizando una función que invierte el estado actual (true/false). Así, cada vez que se hace clic en el botón, el modal alterna entre aparecer y desaparecer.
Yo, lo único que hice fue modificar mi Button así, ¿Estará bien? import React from 'react';import { TodoContext } from '../TodoContext';import './CreateTodoButton.css'; function CreateTodoButton() {  const {openModal, setOpenModal} = React.useContext(TodoContext)  return (    \<button      className="CreateTodoButton"      onClick={        (event) => {                    setOpenModal(!openModal)        }      }    >+\</button>  );} export { CreateTodoButton };
Pregunta: No me funcionó el z-index = 1 en el botón de crear ToDo. Estuve buscando que pudo haber sido el error pero todo parece en order. Lo unico que creo puede ser el error es porque el botón está mas abajo en la jerarquia en el div id=app que el modal-background en el div id=modal. ¿Alguien podría indicarme cual puede ser la solución? Gracias.
## 🦄✨En mi caso hice una estructura que consta de Header y Body para el modal. Para que se pueda añadir un título al modal y se pueda cerrar el mismo a través de una X :3. También realicé el background como un contenedor a parte para que se pueda aplicar un blur al fondo n.n ![](https://static.platzi.com/media/user_upload/image-3d6c584f-119f-4244-9ba7-f7331b4571bd.jpg)
```js import { Context } from '@context';import { useContext } from 'react' const Create_Todo_Button = () => { const { openModal, setOpenModal } = useContext(Context) return (
<button className="text-3xl bg-blue-600 p-4 rounded-full text-white " onClick={() => setOpenModal(!openModal) } > <FiPlus /> </button>
);} export default Create_Todo_Button; ``` Yo lo que hice fué exportar el estado setOpenModal y lo usé al momento de hacer click en el componente CreateTodoButton `import { Context } from '@context';import { useContext } from 'react'` `const Create_Todo_Button = () => { const { openModal, setOpenModal } = useContext(Context) return (
<button className="text-3xl bg-blue-600 p-4 rounded-full text-white " onClick={() => setOpenModal(!openModal) } > <FiPlus /> </button>
);}` `export default Create_Todo_Button;` PD: sorrypor subir dos veces lo mismo es que nunca habia comentado por aquí jeje
asi lo he dejado ![](https://static.platzi.com/media/user_upload/image-819e389a-d9da-4c1e-8f20-e81bf7e4b74d.jpg)
Si el modal se carga automáticamente sin haber sido clicado, simplemente cambie el estado de 'true' a 'false'.
No me queda claro para que utilizar el portal, no lo he agregado a mi codigo y sigue funcionando igual. Alguie me puede explicar por favor? ![](https://static.platzi.com/media/user_upload/image-c1881ad4-bb56-438f-a6e2-f1d0b2600891.jpg)![](https://ibb.co/X5XWJ1W)