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
7 Hrs
21 Min
3 Seg

Obtener y editar TODOs

23/30
Recursos

Aportes 6

Preguntas 1

Ordenar por:

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

Si pruebas agregar otro elemento. Problabemente, verás la sobreescritura de un anterior elemento.

Habia debugueado con muchos console.log hasta darme cuenta que en la asignación de nuevo ID llegaba vacío. Pensé que la variable todos se encontraba en otro scope y habia un error… 😖😖😖 estuve horas así sabiendo el porque, pero sin saber como. Para nuestra buena suerte la solución y explicación a ese error se encuentran en el siguiente video.

En el proceso de editar un todo me salía un error de compilación que no identificaba el id, me ayudó utilizar lo siguiente en la página de EditTodo Page:

const {id} = useParams()

Que extrae el id de los parámetros, pero como string, de tal modo que en el useTodos en el editTodo habría que hacerle un parseInt a ese id para que funcione

Hola a todos, les dejo el código de la clase en TS por si alguien se aventuro como yo en TS y quiere comparar o tambien agregar:

import { TodoForm } from "../components/TodoForm"
import { useTodos } from "../hooks/useTodos"

const NewTodo = () => {

    const { addTodo } = useTodos().stateUpdaters;

    return (
        <div className="form-container">
            <TodoForm 
                submitEvent={(newTodoText)=>{addTodo(newTodoText)}}
            />
        </div>
    )
}

export { NewTodo }

import { useParams } from "react-router-dom";
import { TodoForm } from "../components/TodoForm"
import { useTodos } from "../hooks/useTodos";

const EditTodo = () => {

    const { id } = useParams();
    const { editTodo } = useTodos().stateUpdaters;   

    return (
        <div className="form-container">
            <TodoForm 
                submitEvent={(newTodoText)=>{editTodo((id as string), newTodoText)}}
            />
        </div>
    )
}

export { EditTodo }

import { Dispatch, SetStateAction, useState } from "react";
import { useLocalStorege } from "./useLocalStorage";

export interface ITodo {
  text:string,
  completed:boolean,
  id: string
}

interface State {
  searchedTodos: ITodo[]
  completedTodos: number,
  totalTodos: number,
  searchValue: string,
  loading: boolean,
  error: boolean,
  openModal: boolean,
}

interface StateUpdaters {
  setSearchValue: Dispatch<SetStateAction<string>>
  addTodo: (v:string)=>void
  completeTodo: (v:string)=>void,
  editTodo: (id:string, v:string)=>void
  deleteTodo: (v:string)=>void,
  setOpenModal: Dispatch<SetStateAction<boolean>>
  sincronizeTodos: ()=>void
}

const useTodos = (): { state: State, stateUpdaters: StateUpdaters } => {
  
  const {
    item: todos,
    saveItem: saveTodos,
    loading,
    error,
    sincronizeItem:  sincronizeTodos,
  } = useLocalStorege<ITodo[]>('TODOS_V2', []);

  const completedTodos:number = todos.filter(todo=>todo.completed).length;
  const totalTodos:number = todos.length;
  const [searchValue, setSearchValue] = useState<string>('');
  const [openModal, setOpenModal] = useState(false);

  const searchedTodos = todos.filter(todo=> todo.text.toLowerCase().includes(searchValue.toLowerCase()));

  const addTodo = (text:string) => {
    const id = crypto.randomUUID();
    const newTodos = [...todos]
    newTodos.push({
      text,
      completed: false,
      id
    })
    saveTodos(newTodos)
  }

  const editTodo = (id: string, text:string) => {
    const newTodos = todos.map(todo=>{
      if(todo.id === id) return {
        ...todo,
        text
      };
      return todo;
    })
    saveTodos(newTodos)
  }
  
  const completeTodo = (id: string) =>{
    const newTodos = todos.map(todo=>{
      if(todo.id === id) todo.completed = !todo.completed;
      return todo;
    })
    saveTodos(newTodos);
  }

  const deleteTodo = (id: string) => {
    const newTodos = todos.filter(todo=>todo.id !== id);
    saveTodos(newTodos);
  }

  const state = {
    searchedTodos,
    completedTodos,
    totalTodos,
    searchValue,
    loading,
    error,
    openModal,
  }

  const stateUpdaters = {
    addTodo,
    setSearchValue,
    completeTodo,
    editTodo,
    deleteTodo,
    setOpenModal,
    sincronizeTodos,
  }

  return {
    state,
    stateUpdaters,
  }
}

export { useTodos }
import { FC, FormEvent, useState } from "react"
import { useLocation, useNavigate } from "react-router-dom";
import './TodoForm.css'

interface Props {
    submitEvent: (v:string)=>void,
}

const TodoForm:FC<Props> = ({ submitEvent }) =>{

    const navigate = useNavigate();
    const location = useLocation();
    const [newTodoText, setNewTodoText] = useState('');

    const onCancel = ()=>{
        navigate('/');
    }

    const onSubmit = (e:FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        submitEvent(newTodoText);
        navigate('/');
    }

    return(
        <form onSubmit={onSubmit}>
            <label>{location.pathname === '/new'? 'Escribe tu nueva tarea pendiente':'Edita tu tarea pendiente'}</label>
            <textarea 
                placeholder="Hola, que haremos hoy?"
                value={newTodoText}
                onChange={(event)=>{
                    setNewTodoText(event.target.value)
                }}
            />
            <div className="TodoForm-buttonContainer">
                <button
                    type="button"
                    onClick={onCancel}
                    className="TodoForm-button TodoForm-button--cancel"
                >
                    Cancelar
                </button>
                <button
                    type="submit"
                    className="TodoForm-button TodoForm-button--add"
                >
                    {location.pathname === '/new'? 'Añadir':'Editar'}
                </button>
            </div>
        </form>
    )
}

export { TodoForm }

Obtener y editar TODOs

.
En el componente EditTodoPage vamos a necesitar obtener el id y el nuevo texto que queremos cambiar al TODO.
.
Para obtener el id utilizamos el react hook useParams, mientras que para obtener el texto pasaremos por propiedad a una función submitEvent a TodoForm, donde este será quien internamente pasará el texto a la función editTodo.
.
Por cierto, en TodoForm vamos a mover la navegación debajo y después de llamar a props.submitEvent.
.

import React from 'react';
import { useParams } from 'react-router-dom';
import { TodoForm } from '../../ui/TodoForm';
import { useTodos } from '../useTodos';

function EditTodoPage() {
  const params = useParams();
  const id = Number(params.id);
  
  const { stateUpdaters } = useTodos();
  const { editTodo } = stateUpdaters;
  
  return (
    <TodoForm
      label="Edita tu TODO"
      submitText="Editar"
      submitEvent={(newText) => editTodo(id, newText)}
    />
  );
}

export { EditTodoPage };
// TodoForm/index.js
const onSubmit = (event) => {
    event.preventDefault();
    props.submitEvent(newTodoValue);
    navigate('/');
  };

.
En NewTodoPage se sigue la misma lógica, donde lo único que cambia es la función que se utiliza en submitEvent que en este caso es addTodo y se le pasa solo el texto del nuevo TODO.
.

import React from 'react';
import { TodoForm } from '../../ui/TodoForm';
import { useTodos } from '../useTodos';

function NewTodoPage() {
  const { stateUpdaters } = useTodos();
  const { addTodo } = stateUpdaters;
  
  return (
    <TodoForm
      label="Escribe tu nuevo TODO"
      submitText="Añadir"
      submitEvent={(text) => addTodo(text)}
    />
  );
}

export { NewTodoPage };

.
Finalmente, el mayor cambio se ve reflejado en useTodos.js, donde eliminamos todo lo relacionado con modales y portales; añadimos una función editTodo que es muy similar a la de completeTodo, solo que en lugar de cambiar completed, modificamos el text del TODO. Por último, retornamos a editTodo dentro del objeto stateUpdaters.
.

import React from 'react';
import { useLocalStorage } from './useLocalStorage';

function useTodos() {
	...
  const editTodo = (id, newText) => {
    const todoIndex = todos.findIndex(todo => todo.id === id);
    const newTodos = [...todos];
    newTodos[todoIndex].text = newText;
    saveTodos(newTodos);
  };
  ...
  const stateUpdaters = {
    setSearchValue,
    addTodo,
    completeTodo,
    editTodo,
    deleteTodo,
    sincronizeTodos,
  };

  return { state, stateUpdaters };
}
...

export { useTodos };
Reto futuro solucionado con unas mejoras, cuando el usuario borre por completo el texto vuelve y muestra su texto anterior, una vez lo guarde el nuevo texto este pasa a ser el texto que tiene el usuario y si borra todo aparecerá este, PD intenten publicar un gift pero parece que no se puede y si no seria mas entendible mi explicacion![]() ![](https://www.canva.com/design/DAGC6Lljlwk/TjcDCwi7fpVStjffRBjm4g/edit?utm_content=DAGC6Lljlwk\&utm_campaign=designshare\&utm_medium=link2\&utm_source=sharebutton)![]()![]()![](https://static.platzi.com/media/user_upload/image-f64b70c5-28bb-4baf-a7d4-ff5f115d7032.jpg)![](https://static.platzi.com/media/user_upload/image-60a41a02-56e9-4771-9759-fa5ad489dd07.jpg) ![](https://static.platzi.com/media/user_upload/image-e03d4400-1660-4067-ab27-5b8b18b27490.jpg) ![](https://static.platzi.com/media/user_upload/image-85a544e0-1244-4bc8-97e5-8c1a866e18b5.jpg) ![](https://static.platzi.com/media/user_upload/image-59e8e2ba-5dcb-4a41-b9ef-f0d21947965b.jpg) ![](https://static.platzi.com/media/user_upload/image-68811026-6c55-42bf-ae2f-422bbda1b237.jpg)![](https://static.platzi.com/media/user_upload/image-388d0c6b-315a-4698-987a-4f156b5c7538.jpg)

Esa parte, la de rellenar el textarea con el texto previo de todo es la que no he terminado. El resto lo pude hacer antes de ver la clase.