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

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

14 Días
9 Hrs
5 Min
33 Seg
Curso de React.js

Curso de React.js

Juan David Castro Gallego

Juan David Castro Gallego

Crear TODOs: React Context dentro de React Portals

27/34
Recursos

Aportes 28

Preguntas 8

Ordenar por:

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

Probando la app me conseguí un bug.

Si abres el modal y le das añadir, se agregará un TODO sin texto. Pero tengo la solución.

Existen muchas formas de validación para indicarle al usuario lo que falta. En nuestro caso, por ser un formulario sencillo, basta con agregarle la propiedad required al <textarea /> de TodoForm. quedando así:

<textarea
  placeholder="Cortar cebolla para el almuerzo"
  value={newTodoValue}
  onChange={onChange}
  required
/>

Con eso, el evento submit del formulario no se ejecutará si el textarea está vacío.

Algo que es ⚠️PELIGROSO⚠️ y que sucede con nuestro Todo-List es que crashea si insertamos dos tareas con exactamente el mismo texto. Esto sucede porque en nuestro listado no usamos Números Id únicos. Nuestro “id” es la key del texto. Pero cuando agregamos algo igual, nuestro código no esta preparado para luchar contra eso.
Por eso Agregué una validación con la misma filosofía del buscador, para que a la hora de ingresar un TODO, valida si este ya existe. Funciona así:

Al agregar exactamente el mismo texto. Se dispara un alerta (lo sé, es el alerta default, más adelante lo agregaré estilos xd) y esto evita que se pueda agregar esa tarea. Muestra el aviso, bloquea el botón de agregar, y limpia el input. Aún tiene unos fallos, pero ya cumple con su función.

Lo hice de la siguiente manera:

Cree un nuevo estado en el TodoContextg, el cual funciona igual que nuestro searchValue. También cree un método validatting, que recibe el text del input de agregar, lo valida con nuestro array existente y si encuentra un resultado similar, dispara un cambio de status, la alerta y agrega un nuevo value al input. y abajo del archivo retorno las funciones.

Después, en el formulario, paso mediante el todo context la función validatting y validstatus para poder usarlas de la siguiente manera:

En el onChange llamo a validatting, y le digo al textarea que cuando se active su funcion onFocus, mande a llamar también a validatting.

Y por último, en appUI:

Estoy llamando también a validatting. Esto para que se active desde el momento de la rederización. Me pasaba que si lo activaba desde que se empezaba a escribir, llevaba un delay de un caracter, y no validaba de forma precisa, por eso lo implementé de esa manera.

Es algo confuso, si gustan ver todo el código acá les dejo mi repo: https://github.com/Alvarenga144/TodoList-Reactjs18 🫡

Para evitar que en la descripcion se guarden con espacios vacios al inicio y al final podemos utilizar la funcion trim() ademas se puede hacer una validacion para que la descripcion del todo no este vacia

desabilite el boton de anadir y agregue unos estilos si no es una descripcion de todo valida

la única duda que tengo es… ¿qué pasó con la taza? jajajaja

Para cerrar la ventana modal clicando fuera yo lo he conseguido hacer así:
.
El el archivo Modal.jsx he agregado el useContext y en el evento onClick del div cierro la modal:

function Modal({ children }) {
    const {setOpenModal} = useContext(TodoContext)

    return ReactDOM.createPortal(
        <div className="ModalBackground" onClick={() => setOpenModal(false)}>
            {children}
        </div>,
        document.getElementById("modal")
    )
}

.
Luego en el archivo TodoForm.jsx he añadido un div por encima del formulario y a su evento onClick le he añadido e.stopPropagation() para que al clicar aquí no se cierre la modal

function TodoForm() {
    const {addTodo, setOpenModal} = useContext(TodoContext)
    const [textValue, setTextValue] = useState("")

    function onSubmit(e) {
        e.preventDefault()
        addTodo(textValue)
        setOpenModal(false)
    }

    return (
        <div onClick={(e) => e.stopPropagation()}>
            <form onSubmit={onSubmit}>
                <label>Escribe tu nuevo TODO</label>
                <textarea 
                    placeholder="Cortar cebolla..." 
                    value={textValue} 
                    required
                    onChange={(e) => setTextValue(e.target.value)} 
                />
                <div className="TodoForm-buttonContainer">
                    <button 
                        type="button" 
                        className="TodoForm-button TodoForm-button--cancel"
                        onClick={() => setOpenModal(false)}
                    >
                        Cancelar
                    </button>
                    <button 
                        type="submit" 
                        className="TodoForm-button TodoForm-button--add"
                    >
                        Añadir
                    </button>
                </div>
            </form>
        </div>
    )
}

lo que yo vi … 😄

Lo hice sin usar el Usecontex, pero la termine

me corto un poquito el ritmo que a mitad del proceso, realizara un orden, yo desde un principio tenia otro orden, y clases como el contex y el usecontext no lo hice porque era muy abrumador tantos cambios. y ahora estoy sufriendo porque no se como ejecutar el addTodo cuando se le da al boton crear, agregue una pregunta mostrando como lo tengo por si se apiadan y me quieren ayudar, gracias

Para que visual studio ayude con el autocompletado en este caso del "todoContext" en la importación ,el archivo debe estar abierto , o en su defecto una vez que lo abren y cierran les aparecera el autocompletado.
El mejor manager de tarea, bojack <3 ![](https://static.platzi.com/media/user_upload/image-5f6ff525-a708-4e87-8522-bb23f012a07a.jpg)
hola tengo un problema que no logro resolver, cuando recargo la pagina efectivamente me carga pero a los 2 segundos la pagina queda totalmente en blanco, luego cuando miro la consola me aparece el siguiente error "Uncaught TypeError: todo.text.toLowerCase is not a function at TodoContext.js:23:1" este es el codigo que tengo en ese archivo y esa linea const searchedTodos = todos.filter(        (todo) => {        const todoText = todo.text.toLowerCase();        const searchText = searchValue.toLowerCase();        return todoText.includes(searchText);        }    );```js const searchedTodos = todos.filter( (todo) => { const todoText = todo.text.toLowerCase(); const searchText = searchValue.toLowerCase(); return todoText.includes(searchText); } ); ```he intendado y no se como solucionarlo

Hola, en el punto en donde esta la app aqui en esta clase, se le puede añadir que descomplete una Todo, con esta linea

newTodos[todoIndex].completed = !newTodos[todoIndex].completed;

aqui

  const completeTodo = (text) => {
    const newTodos = [...todos];
    const todoIndex = newTodos.findIndex(todo => todo.text === text);
    // newTodos[todoIndex].completed = true;
    newTodos[todoIndex].completed = !newTodos[todoIndex].completed;
    saveTodos(newTodos);
  };
Juan David Castro Gallego como estas, tengo una duda con respecto a una funcionalidad extra que deseo colocar en el proyecto el cual calcula el numer de dias desde la creacion del proyecto hasta el cierre de la misma pero tengo dos dudas la primera es como hago que se vea mejor en las fechas, poder lograr una fecha corta y lo otro es calcular los dias con fecha del cierre y de apertura, te adjunto mi repositorio. <https://github.com/roanrevi/listaDePendientes.git> ![](https://static.platzi.com/media/user_upload/image-c690d487-13af-4377-81f6-3fb46e508a9e.jpg)
Tengo una pregunta, por que en el formulario si se puede llamar al contexto con useContext, y dentro del boton createTodoButton si se lo debe pasar como props? yo hice la prueba desde el componente del boton de llamar al contexto para usar la funcion de abrir el modal, pero dio error. alguien sabe por que? es por alguna dependencia ciclica?
me podrian orientar, porque mi todoform quedo asi? gracias.![](https://static.platzi.com/media/user_upload/Captura%20de%20Pantalla%202024-03-28%20a%20la%28s%29%2012.23.45-25b8033a-8bb1-449c-99c7-325dcfca3149.jpg)![]()

opte por usar React Hook Form para ahorrar un poco de tiempo

Tengo que admitir que el proyecto lo hice de una manera un poco distinta, pero siguiendo el curso a su ritmo, en mi caso no utilice un modal para agregar las tareas porque me fue un poco confuso pero de todas maneras pongo el código para quienes quieran agregar de manera directa las tareas

Observando esta manera de pasar nuevos estados al useState(), habia una forma en la que se realizaba la operacion dentro de una funcion -> (previous_value) => { return [...previous_value, valor_a_agregar]}. Hay alguna implicacion, o mejor practica para actualizar este estado de variables?

Jejeje “Juan toca cortar”. jejeje

Bien! Ahora solo me falta agregar la posibilidad de cambiar los colores de fondo e idioma, y otra forma de agregar todos mediante otro boton (reto personal), pero GG
Yo estoy agarrando el valor de input de manera diferente y me gustaria saber si lo estoy haciendo bien o mal. `let textInput = document.querySelector('textarea');` `addTodo(textInput.value);` `textInput.value = '';` Simplemente estoy "agarrando" el elemento con un querySelector y mandando el valir a la funcion addTodo. ¿Esta bien o mal? ¿Puede causarme un problema futuro? ¿Tengo que dejar la programacion y hacer otro tipo de cosas? Ayudenme por favor
Yo para agregar TODOS lo que hice fue que desde la misma función TodoProvider cree el estado *const* \[newTask, setNewTask] = useState(""); luego *const* addTodo = () *=>* { i*f* (newTask*.*trim()) { *const* newToDos = \[*...*toDo, { *text*: newTask, *completed*: *false* }];      saveToDos(newToDos);      setNewTask("");      handleCloseModal(); } } *const* handleCloseModal = () *=>* setOpenModal(*false*); *const* handleTaskChange = (event) *=>* setNewTask(event*.*target*.*value); ya en el TodoForm ![](https://static.platzi.com/media/user_upload/image-7e1908c5-2761-4e7a-a2c6-e21e452145a0.jpg)
![](https://static.platzi.com/media/user_upload/image-115b80e3-b69a-4b77-afd6-126d6e38d328.jpg)

No se si alguien se dió cuenta que hasta este punto Juan no agregó el segundo argumento al React.useEffect, es decir debió agregar [itemName, initialValue], porque de lo contrario está teniendo un ciclo infinito, la app con el tiempo se le va colgar…

se siente tan bien terminar algo!
Module not found: Error: Can't resolve '../TodoForm' in '/Users/rosanasuarez/develop.js/Lista-de-Tareas/src/App' ERROR in ./src/App/AppUI.js 14:0-39 Module not found: Error: Can't resolve '../TodoForm' in '/Users/rosanasuarez/develop.js/Lista-de-Tareas/src/App' tengo el siguiente error y ya no se como solucionarlo, aluna sugerencia? Considerando que esta exportado e importado, pero hay algo que evidentemente no estoy viendo
13: 00 :)
HE copiado tal cual el código y no funciona el botón de agregar Todo... se pone la pantalla en blanco y ano se que hacer de todo lo investigado por favor respondan alguna vez... solo le dan like en automático a mis preguntas ya estoy cansado de que no me brinden una solución, lo tomo como un total falta de respeto y desinterés...