Fundamentos de navegación en la web

1

Navegación en React Router: Fundamentos y Práctica

2

Renderizado en el servidor vs aplicaciones de una sola página

3

React Router DOM 6: Componentes y Navegación Eficiente

Introducción a React Router DOM 6

4

React Router DOM 6: Instalación y Configuración Básica

5

Tipos de Routers en React: Browser, Hash y Memory

6

Rutas Dinámicas con React Router DOM 6

7

Navegación Dinámica con React Router: Link y NavLink

8

Rutas dinámicas en React con UseParams y React Router DOM 6

9

Uso de React Hook useNavigate en React Router DOM 6

10

Rutas anidadas en React Router DOM: Uso del componente Outlet

Fake authentication con React Router DOM 6

11

Rutas Protegidas en React: Autenticación y Autorización con Hooks

12

Navegación Segura con Autenticación en React

13

Protección de rutas con React Router y Hooks

14

Autorización y Roles en Aplicaciones Web

15

Manejo de estado avanzado en React: planetando soluciones efectivas

16

Redirección post-login con useLocation en React Router DOM

17

Roles y Permisos en React con Rutas Dinámicas y Autenticación

React Router en TODO Machine

18

Proyecto React Router: Rutas Dinámicas con Todo Machine

19

Estructura de Carpetas y Rutas en React con React Router DOM

20

Maquetación de botones para editar To-Do Items en React

21

Generación de IDs únicos en JavaScript

22

Rutas Dinámicas en React: Manejo y Navegación Eficiente

23

Métodos avanzados para manipular custom hooks en React

24

Transmisión de Datos en React con useLocation y useState

25

Proyecto React Router: Desplegando en GitHub Pages

Próximos pasos

26

Actualización de URL con búsqueda React Router

27

Retos de Migración en Proyectos React: React Router DOM 5 vs. 6

28

React.js: Creación de Rutas y Navegación en Aplicaciones Web

29

Clonación de React Router con Componentes y Hooks

30

Navegación con React Router DOM: Rutas, Hooks y Autenticación

No tienes acceso a esta clase

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

Retos de Migración en Proyectos React: React Router DOM 5 vs. 6

27/30
Recursos

¿Cuál es el reto al trabajar con paquetes desactualizados en empresas?

Cuando nos enfrentamos al mundo real de una empresa, no siempre trabajamos con las tecnologías más recientes. Así que, ¿qué ocurre cuando te encuentras con versiones antiguas de ciertas herramientas, como React Router DOM 5, en lugar de las actuales que usaste para tus proyectos personales? La respuesta, según la experiencia compartida, es que debes adaptarte al entorno laboral que encuentres. Es crucial entender que, aunque el aprendizaje y el impulso por estar al día son importantes, muchas empresas aún operan con configuraciones que garantizan estabilidad y continuidad en sus aplicaciones.

¿Qué implica regresar a versiones anteriores de paquetes?

  • Challenge personal y profesional: Volver a usar versiones anteriores nos desafía a encontrar soluciones con herramientas que quizás no sean tan avanzadas como las actuales.
  • Contexto empresarial: Las empresas priorizan la estabilidad y eficiencia de sus operaciones diarias sobre estar a la vanguardia tecnológica.
  • Rendimiento y compatibilidad: Algunas veces, la migración hacia versiones más nuevas no proporciona un beneficio directo en el rendimiento ni mejora la compatibilidad de la API que justifique el cambio.

¿Cómo abordar el trabajo en entornos tecnológicos anteriores?

Trabajar en un entorno que no siempre está a la vanguardia puede parecer un retroceso, pero tiene su propio valor y lecciones:

  1. Flexibilidad y adaptabilidad: Ser capaz de adaptarse a diferentes versiones y tecnologías es una habilidad valiosa.
  2. Concentrarse en la funcionalidad: Es esencial mantener el enfoque en resolver problemas reales y proporcionar valor inmediato, más que obsesionarse con actualizar herramientas.
  3. Justificación de cambios tecnológicos: Ante propuestas de actualización, siempre tendrás que justificar cómo el cambio aporta valor, como mejor rendimiento o funcionalidad crucial para el usuario.

¿Por qué podría no ser prioritario actualizar las dependencias?

En un caso hipotético donde se plantee la migración de React Router DOM de la versión 5 a la 6, la discusión puede centrarse en aspectos prácticos:

  • Costo-beneficio: ¿Realmente el beneficio justifica el esfuerzo y tiempo de hacer la actualización?
  • Impacto en el usuario: Mejorar las características que impactan directamente al usuario puede ser más prioritario que internalizar novedades de nuevas versiones.
  • Esfuerzo en el cambio: La migración implica no solo cambiar el package.json, sino adaptar todo el código preocupado por las dependencias usadas.

Este es un escenario muy común en empresas consolidadas y describe la necesidad de balancear entre innovar y preservar la estabilidad de los productos ya funcionando. Y aunque pueda parecer restrictivo, este tipo de retos nos preparan para enfrentar situaciones similares en entornos laborales reales, donde la adaptabilidad y la habilidad para trabajar con diversas versiones se vuelven cruciales. Por lo tanto, nunca subestimes el valor de dominar versiones anteriores, porque te dota de una perspectiva más amplia y flexible.

Aportes 19

Preguntas 1

Ordenar por:

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

Los cambios que hice para que funcionará con React router dom versión 5 fueron:

En el archivo App.js

En el archivo TodoForm/index.js

En el archivo HomePage.js

Hace poco me paso que estaba actualizando esta libreria a la v6 en un proyecto grande. Estaba haciendo todos los cambios hasta que me tope que en la ultima version habian eliminado un feature que estabamos usando para bloquear la navegacion.
Hablo de usePrompt y useBlocker.
Esto se usa si por ejemplo el usuario esta completando un formulario y antes de guardar los cambios quiere navegar a otra ruta. Nosotros le mostramos un modal de confirmacion antes de hacer la navegacion si tiene cambios. Entonces usamos ese feature. Pero en la version 6 no se puede (o no descubri como) hacerlo.

https://github.com/remix-run/react-router/issues/8139

Aquí les dejo la documentación de react-router v5 😎👇

https://v5.reactrouter.com/web/guides/quick-start 💚

muy válido para entender por qué no van a actualizar el curso práctico de React

Hecho! Este me parece uno de los mejores retos del curso, sin él nunca me hubiera probado una versión anterior de nada.
.
La mayoría de cambios son superficiales, cambian las rutas y algunos hooks por otros. Me voy a explayar en el reto de los query params, que sí es más complicado.
.
Anteriormente, se podía usar el hook useSearchParams. Lamentablemente este no está en la V5. Lo que hice después de muuuucha investigación fue hacer un hook propio (fuertemente inspirado en respuestas de StackOverflow)
.

useQuery.js

import { useMemo } from 'react'
import { useLocation } from 'react-router-dom'

export function useQuery(value) {
    const { search } = useLocation()
    const setQuery = useMemo(() => new URLSearchParams(search), [search])
    const query = setQuery.get(value)
    return [query, setQuery]
}

Luego lo implementé de la siguiente manera:

TodoSearch.js

import React from 'react'
import { useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import { useQuery } from '../hooks/useQuery'

export function TodoSearch({ setSearchValue, searchValue, loading }) {
    const [searchQuery] = useQuery('search')
    const history = useHistory()

    const onSearchValueChange = ({ target: { value } }) => {
        setSearchValue(value)
        history.push({ search: `search=${value}` })
    }

    useEffect(() => {
        if (searchQuery && searchQuery !== searchValue)
            setSearchValue(searchQuery)
    }, [searchQuery, setSearchValue, searchValue])

    return (
        <input
            className={`TodoSearch ${loading && 'TodoSearch--loading'}`}
            onChange={onSearchValueChange}
            value={searchQuery ?? ''}
            placeholder="Search a To-Do"
        />
    )
}

Se siente tan fácil una vez terminado… no fue directo, pero fue muy entretenido y un gran desafío.

Documentación de React Router DOM V5

Documentación aquí

React Router V5 vs V6 dev.to
Documentación de React Router reactrouter.com

No fue tan sencillo como parece… Batalle mucho con el reto de TodoSearch.
Dejo el codigo por si a alguien le sirve de apoyo.

function TodoSearch({ searchValue, setSearchValue, loading }) {
  const history = useHistory();

  const onSearchValueChange = (event) => {
    const value = event.target.value;
    setSearchValue(value);
    history.push({ search: value });  
//modificar la url y guarda todo en location
  };

const param = history.location.search.slice(1);
// usar el metodo slice para quitar  '?' al inicio del string

 const searchParam = decodeURI(param) ?? searchValue;
// decodeURI  es una funcion de javascript ayuda a decodificar la url.
  return (
    <input
      className="TodoSearch"
      placeholder="Cebolla"
      value={searchParam}
      onChange={onSearchValueChange}
      disabled={loading}
    />
  );
}

Lo único raro, fue switch en vez de routes y route.

Hola bueno los compañeros ya compartieron como cambiar a la version 5 utilizando distintos valores como Swich y history. Yo vengo a compartir mi solución sobre el **search🥸**, ya que estuve como loco un día entero jajaj. Lo que hice fue crear la ruta dinámica con el **path="/search/:slug?"** que quiere decir que puede recibir un slug o no para que no se rompa todo. Despues en el evento del Input se debe encargar de actualizar el estado (que renderiza las tareas encontradas) y tambien actualizar la ruta de esta forma : {   history.push({   pathname:"/search", search:event.target.value,    }) //ruta setSearchValue(event.target.value)//estado } Porque este quilombo de pasar el estado de search? Para asi poder hacer una validación si el usuario entra con la url de una busqueda. Aclaro que envolví esta validación en un **Efectt** que su **ciclo de vida es de una ejecucion**, porque me pareció lo mas adecuado para un caso real... **La ventaja** es que no se renderice cada vez que el usuario escriba una letra, solo si el usuario entre por primera vez con esa busqueda realizada. Siento que no es óptimo que se ejecute imaginando que fuesen consultas a una API por ejemplo. La desventaja es que si decide navegar por la URL no funcionará al menos que refresque la pagina. Les dejo el código, si hay algun error háganmelo saber quizas hice cualquiera 😂. .; ```jsx //APP <Route exact path="/search/:slug?" > <HomePage /> </Route > //TodoSearch function ToDoSearch({ searchValue, setSearchValue, loading }) { const location = useLocation(); const history = useHistory(); React.useEffect(()=>{ if(location.search){ setSearchValue(location.search.replace("?","")) console.log("EJECUCION") } },[]) //aca podria poner que dependa de searchValue pero tendría un costo alto de rendimiento return ( <input placeholder="Busca Tareas" className="search-input" value={searchValue} onChange={(event) => { history.push({ pathname:"/search", search:event.target.value, }); setSearchValue(event.target.value) }} disabled={loading} /> ) } ```

Reto: TODO Machine con React Router DOM 5

.
El reto es replicar el mismo comportamiento de la aplicación con React Router DOM 5.
.
Para ello vamos a mantener la misma estructura de carpetas que utilizamos para la aplicación con React Router DOM 6 pero modificando algunos archivos donde algunos hooks o componentes proporcionados por este no existan o funcionen distintamente en la versión 5.
.
Para este reto hemos utilizado la versión 5.3.4 de React Router DOM.
.

"react-router-dom": "^5.3.4"

.
En src/routes/App.js ya no se usa el componente Routes de la versión 6, sino que se usa Switch. En lugar de element para definir el componente que se debe renderizar ahora utilizamos component.
.
Otra diferencia es que en la versión 6 element acepta un elemento de React directamente como <HomePage />, mientras que en la versión 5 component solo acepta una referencia a un componente como HomePage.
.
En la versión 6, es más directo usar el prop element={<p>Not Found</p>} con JSX, mientras que en la versión 5, se utiliza una función que retorna JSX component={() => <p>Not Found</p>}.
.
en la versión 6 Routes entiende de forma implícita cuándo una ruta es exacta, no se usa exact porque el enrutador lo maneja automáticamente, mientras que en la versión 5 usa exact para asegurar que la ruta exacta se corresponda.
.

import React from "react";
import { HashRouter, Route, Switch } from "react-router-dom";
import { EditTodoPage } from "./edit/EditTodoPage";
import { HomePage } from "./home/HomePage";
import { NewTodoPage } from "./new/NewTodoPage";

function App() {
  return (
    <HashRouter>
      <Switch>
        <Route exact path="/" component={HomePage} />
        <Route path="/new" component={NewTodoPage} />
        <Route path="/edit/:id" component={EditTodoPage} />
        <Route path="*" component={() => <p>Not Found</p>} />
      </Switch>
    </HashRouter>
  );
}

export { App };

.
En el componente HomePage, vamos a remplazar useNavigate por useHistory para la navegación con React Router DOM 5. El hook useHistory utiliza un método push para navegar a una ruta.
.
Ambas versiones permiten pasar un estado a través de la navegación, en la versión 6 con navigate('/edit/' + todo.id, { state: { todo } }) y en la versión 5 con history.push('/edit/' + todo.id, { todo }).
.

import React from "react";
import { useHistory } from "react-router-dom";
import { useTodos } from "../useTodos";
import { TodoHeader } from "../../ui/TodoHeader";
import { TodoCounter } from "../../ui/TodoCounter";
import { TodoSearch } from "../../ui/TodoSearch";
import { TodoList } from "../../ui/TodoList";
import { TodoItem } from "../../ui/TodoItem";
import { TodosError } from "../../ui/TodosError";
import { TodosLoading } from "../../ui/TodosLoading";
import { EmptyTodos } from "../../ui/EmptyTodos";
import { CreateTodoButton } from "../../ui/CreateTodoButton";
import { ChangeAlert } from "../../ui/ChangeAlert";

function HomePage() {
  const history = useHistory();
  const { state, stateUpdaters } = useTodos();

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

  const {
    completeTodo,
    deleteTodo,
    setSearchValue,
    sincronizeTodos,
  } = stateUpdaters;

  return (
    <React.Fragment>
      <TodoHeader loading={loading}>
        <TodoCounter totalTodos={totalTodos} completedTodos={completedTodos} />
        <TodoSearch searchValue={searchValue} setSearchValue={setSearchValue} />
      </TodoHeader>

      <TodoList
        error={error}
        loading={loading}
        totalTodos={totalTodos}
        searchedTodos={searchedTodos}
        searchText={searchValue}
        onError={() => <TodosError />}
        onLoading={() => <TodosLoading />}
        onEmptyTodos={() => <EmptyTodos />}
        onEmptySearchResults={(searchText) => (
          <p>No hay resultados para {searchText}</p>
        )}
      >
        {(todo) => (
          <TodoItem
            key={todo.id}
            text={todo.text}
            completed={todo.completed}
            onEdit={() => {
              history.push("/edit/" + todo.id, { todo });
            }}
            onComplete={() => completeTodo(todo.id)}
            onDelete={() => deleteTodo(todo.id)}
          />
        )}
      </TodoList>

      <CreateTodoButton
        onClick={() => history.push("/new")}
        // setOpenModal={setOpenModal}
      />

      <ChangeAlert sincronize={sincronizeTodos} />
    </React.Fragment>
  );
}

export { HomePage };

.
En TodoForm es hacer lo mismo, remplazar useNavigate por useHistory.
.

import React from 'react';
import { useHistory } from 'react-router-dom';
import './TodoForm.css';

function TodoForm(props) {
  const history = useHistory();
  const [newTodoValue, setNewTodoValue] = React.useState(props.defaultTodoText || '');

  const onChange = (event) => {
    setNewTodoValue(event.target.value);
  };
  const onCancel = () => {
    history.push('/');
  };
  const onSubmit = (event) => {
    event.preventDefault();
    props.submitEvent(newTodoValue);
    history.push('/');
  };

  return (
    <form onSubmit={onSubmit}>
      <label>{props.label}</label>
      <textarea
        value={newTodoValue}
        onChange={onChange}
        placeholder="Cortar la cebolla oara el almuerzo"
      />
      <div className="TodoForm-buttonContainer">
        <button
          type="button"
          className="TodoForm-button TodoForm-button--cancel"
          onClick={onCancel}
          >
          Cancelar
        </button>
        <button
          type="submit"
          className="TodoForm-button TodoForm-button--add"
        >
          {props.submitText}
        </button>
      </div>
    </form>
  );
}

export { TodoForm };

.
Finalmente, en TodoSearch es donde se dio el mayor cambio, puesto que habíamos implementado búsqueda por navegación con useSearchParams. Sin embargo, este hook no existe en la versión 5 de React Router DOM.
.
Lo que se hizo fue utilizar useHistory y useLocation para obtener la propiedad search de useLocation, luego cada que escribamos algo en el input de búsqueda vamos a navegar con useHistory hacia el pathname / con ?search=${event.target.value} concatenado con lo que escribamos en dicho input.
.
Finalmente, en un useEffect revisamos que si el search empieza con ?search= significa que hemos accedido directamente a la búsqueda por la url, así que recuperamos el valor de la búsqueda, lo decodificamos en caso de que la búsqueda contuviera espacios representados como %20 y cambiamos el estado de searchValue mediante setSearchValue.
.
De esta manera obtendremos la búsqueda por navegación tanto por el input de búsqueda, como desde la url.
.

import React, { useEffect } from "react";
import "./TodoSearch.css";
import { useHistory, useLocation } from "react-router-dom";

function TodoSearch({ searchValue, setSearchValue, loading }) {
  const { search } = useLocation();
  const history = useHistory();

  const onSearchValueChange = (event) => {
    setSearchValue(event.target.value);
    history.push({
      pathname: "/",
      search: `?search=${event.target.value}`,
    });
  };

  useEffect(() => {
    if (search.startsWith("?search=")) {
      setSearchValue(decodeURIComponent(search.substring(8)));
    }
  }, [searchValue]);

  return (
    <input
      className="TodoSearch"
      placeholder="Cebolla"
      value={searchValue}
      onChange={onSearchValueChange}
      disabled={loading}
    />
  );
}

export { TodoSearch };

Aquí les comparto mi repositorio en github en donde la rama main está con react router dom v6, mientras que la rama proyecto-react-router-dom-5, la aplicación está con react router dom v5.

Repositorio:
curso-react-router-proyecto2

Dejo el commit y la rama para la migracion bien explicados en inglés: \- My english version branch and commit: <https://github.com/SebaMat3/react-todo/tree/react-router-v5)> Branch name: react-router-v5 Commit message: feat(routing): implement React Router v5 \- Replace useNavigate with useHistory for navigation \- Update URL search params handling with useLocation \- Maintain route state passing between components \- Keep nested route component structure in App.js \- Preserve existing route params functionality \- Handle todo edit state passing through history.push Breaking changes: \- Remove useSearchParams in favor of URLSearchParams API \- Update navigation methods across components
Les dejo "ToDos" los cambios que hice por si alguien también quiere tirar la toalla, para que no la tire!!! Como yo casi quería dejar el curso en este punto y luego me acordé del tema de PASITO a PASITO, una cosa a la vez y tener tambien visión global de las cosas y que esto esta hecho por personassssssss. No robots despreciables sin compasión. Me asocie con San ChatGPT, me encomende a los dioses de la internet que siempre usa el profe y empecé a cambiar lo que fui identificando como necesario: Pasos para el cambio: Ejecutar: `npm uninstall react-router-dom` Ejecutar: `npm install react-router-dom@5` Reemplazar: `Routes` por `Switch` Reemplazar: `<Route path="/xxx" element={< xxx />} />` por `<Route path="/xxx" component={ xxx } />` Reemplazar: `<Route path="/xxx" element={<Navigate to="/xxx" />} /> `por `<Redirect from="/xxx" to="/xxx" />` Reemplazar: `const navigate = useNavigate()` por `c` `const history = useHistory();` Reemplazar: `import { Routes, Navigate, useNavigate } from 'react-router-dom';` por `import { Switch, Redirect, useHistory }  from 'react-router-dom';` Reemplazar: `navigate('/xxx');` por `history.push('/xxx');` Remplazar: `onEdit={() => navigate(/edit/${toDo.id}, {state: toDo.text })}` por ``onEdit={()=> history.push(/edit/${toDo.id}?text=${toDo.text}`)}`` En el componente hijo: Añadir : `import { useHistory } from "react-router-dom";` `const history = useHistory()` Los Remplazos que más me sacaron la piedrunchis..., el tiempo y mas me hicieron sufrir: (me ayudo chatGPT 😉) En el componente hijo de Editar: Reemplazar: `if (location.state) {` `previousText = location.state} `por `if (location.search) {` `const params = new URLSearchParams(location.search) previousText = params.get('text')}` Si después de todo esto sigue fallando, le mandas a chatGPT todo tu código y que te acabe de ajustar la solución. Hay que mandar homepage, las dos rutas de edit y add, la app.js y el código de useToDos por si acaso. Suerte!
Les dejo "ToDos" los cambios que hice por si alguien también quiere tirar la toalla, para que no la tire!!! Como yo casi quería dejar el curso en este punto y luego me acordé del tema de PASITO a PASITO, una cosa a la vez y tener tambien vision global de las cosas y que esto esta hecho por personassssssss. No robots despreciables sin compasion. Me asocie con San ChatGPT, me encomende a los dioses de la internet que siempre usa el profe y empecé a cambiar lo que fui identificando como necesario: Pasos para el cambio: Ejecutar: `npm uninstall react-router-dom` Ejecutar: `npm install react-router-dom@5` Reemplazar: `Routes` por `Switch` Reemplazar: <;Route path="/xxx" element={< xxx />} /> por \<Route path="/xxx" component={ xxx } /> Reemplazar: \<Route path="/xxx" element={\<Navigate to="/xxx" />} /> por \<Redirect from="/xxx" to="/xxx" /> Reemplazar: `const navigate = useNavigate()` por `const history = useHistory();` Reemplazar: `import { Routes, Navigate, useNavigate } from 'react-router-dom';` por `import { Switch, Redirect, useHistory }  from 'react-router-dom';` Reemplazar: `navigate('/xxx');` por `history.push('/xxx');` Remplazar: onEdit={() => navigate(`/edit/${toDo.id}`, {state:  toDo.text })} por `onEdit={()=> history.push(`/edit/${toDo.id}?text=${toDo.text}`)} En el componente hijo: Añadir : `import { useHistory } from "react-router-dom";` `const history = useHistory()` Los Remplazos que más me sacaron la piedrunchis..., el tiempo y mas me hicieron sufrir: (me ayudo chatGPT 😉) En el componente hijo de Editar: Reemplazar: if (location.state) { previousText = location.state} por if (location.search) { const params = new URLSearchParams(location.search) previousText = params.get('text')} Si después de todo esto sigue fallando, le mandas a chatGPT todo tu código y que te acabe de ajustar la solución. Hay que mandar homepage, las dos rutas de edit y add, la app.js y el código de useToDos por si acaso. Suerte!
Les dejo "ToDos" los cambios que hice por si alguien también quiere tirar la toalla, para que no la tire!!! Como yo casi quería dejar el curso en este punto y luego me acordé del tema de PASITO a PASITO, una cosa a la vez y tener tambien vision global de las cosas y que esto esta hecho por personassssssss. No robots despreciables sin compasion. Me asocie con San ChatGPT, me encomende a los dioses de la internet que siempre usa el profe y empecé a cambiar lo que fui identificando como necesario: Pasos para el cambio: Ejecutar: `npm uninstall react-router-dom` Ejecutar: `npm install react-router-dom@5` Reemplazar:       `Routes`   por `Switch` Reemplazar:       \<Route path="/xxx" element={< xxx />} />   por \<Route path="/xxx" component={ xxx } /> Reemplazar: \<Route path="/xxx" element={\<Navigate to="/xxx" />} />  por \<Redirect from="/xxx" to="/xxx" /> - Reemplazar:       `const navigate = useNavigate()`  por `const history = useHistory();` Reemplazar: `import { Routes, Navigate, useNavigate } from 'react-router-dom';`  por `import { Switch, Redirect, useHistory }  from 'react-router-dom';` Reemplazar: `navigate('/xxx');`  por `history.push('/xxx');` Remplazar: `onEdit={() => history.push(`/edit/${toDo.id}`, {state:  toDo.text })  por `onEdit={() => history.push(`/edit/${toDo.id}?text=${toDo.text}`)}  En el componente hijo:   Añadir : `import { useHistory } from "react-router-dom";`  `const history = useHistory()` Los Remplazos que más me sacaron la piedrunchis..., el tiempo y mas me hicieron sufrir: (me ayudo chatGPT 😉) En el componete hijo de Editar: Reemplazar: if (location.state) { previousText = location.state}  por if (location.search) { const params = new URLSearchParams(location.search)      previousText  = params.get('text')} Si despues de todo esto sigue fallando, le mandas a chatGPT todo tu codigo y que te acabe de ajustar la solucion. Hay que mandar homepage, las dos rutas de edit y add, la app.js y el codigo de useToDos por si acaso. Suerte!
Recuerdo la primera vez que me puse aprender React, en ese tiempo aún tenían una batalla campal por ver que router usar (Solo que yo no lo sabía), el router estaba, solo estaba; cuando buscabas información sobre el tema terminabas más cerca de la batalla campal que de la solución; ahora es la guerra por los routers está digamos que en relativa paz; este reto no es dificil, solo que volver a esos tiempos es \* Recuerdos de Vietnam \* recordar el como intentaba usar cosas de las que no sabía lo suficiente, que ahora veo y es más facil, este reto me recordó un montón esos días... Así que gracias por el ataque de nostalgia, realmente he aprendido mucho desde esos días

tuve unos errores orribles, los cuales no pude salir, aquí les muestro cuales eran

Tenia todos los imports que se necesitaban pero me seguian pasando los errores, como por ejemplo el primero que me dice que en ese archivo index de el folder TodoForm no encuentra el useHistory donde si lo estoy importando

Oigaan.
Lo logre. Utilizando
Switch, useHistory y useLocation de la V5

Pero el input de search porque cuando quiero escribir me queda invalido hasta que hago click?

por cada letra que quiero colocar es un click que debo hacer al input