umm, mi lado radical eliminó todo lo que tenía delineado amarillo, pero mi lado prudente hizo commit antes de eso.
Fundamentos de navegación en la web
¿Cuándo necesitas React Router?
SSR vs. Single Page Applications
Versiones de React Router: ¿Por qué son tantas? ¿Cuál elegir?
Introducción a React Router DOM 6
Instalación de React Router DOM 6
BrowserRouter vs. HashRouter
Route: componentes de navegación
Link vs. NavLink
useParams: rutas dinámicas
useNavigate: historial de navegación
Outlet: nested routes
Fake authentication con React Router DOM 6
useAuth: login y logout
Menú con rutas públicas y privadas
Navigate y redirects: protegiendo rutas privadas
Roles y permisos
Reto: composición de componentes con navegación
Reto: UX de login y logout
Reto: roles complejos
React Router en TODO Machine
Integrando React Router a proyectos en React
Creando las rutas de TODO Machine
Botón de editar TODOs
Generador automático de IDs
Cambiando modales por navegación
Obtener y editar TODOs
useLocation: transferencia de datos por navegación
Deploy con React Router en GitHub Pages
Próximos pasos
Reto: página de búsquedas con navegación
Reto: TODO Machine con React Router DOM 5
Reto: PlatziMovies con React Router
Reto: crea tu propio React Router
Espera más cursos de React.js
You don't have access to this class
Keep learning! Join and start boosting your career
Managing routes and navigation in React applications can become a challenge if an efficient approach is not used. Historically, this could include additional dependencies such as portals and modals, but as the instructor describes, there is a trend in the industry to simplify the design by using routes instead of portals, leveraging React Router DOM. The following steps will guide you on how to effectively replace portals with routes to improve your application's navigation.
The first step is to identify all components related to the use of portals, such as modals. In the code, you may notice instructions such as OpenModal
that need to be removed. Once located, they are replaced with routes using React Router DOM's useNavigate
. The navigate
function is imported and configured appropriately to allow buttons to redirect to specific new routes, such as /new
.
import { useNavigate } from 'react-router-dom';
const MyComponent = () => { const navigate = useNavigate();
return ( <button onClick={() => navigate('/new')}>Create New To-Do</button> );};
The next step is to modify each component that interacted with the portals to work with the new routing logic. This involves updating the properties that were received and defined in components such as ToDoForm
. The properties that controlled the visibility of the modal must be replaced with events that manipulate routes.
// Before<button onClick={props.setOpenModal(!props.openModal)}></button>
// After<button onClick={props.onClick}></button>
The To-Dos create and edit forms are central to the application. Each is encapsulated in a new page with logic to send the entered data through props
and handle related events. Here the use of navigate
allows returning to home after a successful submission.
const NewToDoPage = () => { const navigate = useNavigate(); const handleAddToDo = () => { // Logic to add To-Do // Then redirect to home navigate('/'); };
return ( <ToDoForm label="Write your new to-do" submitText="Add" onSubmit={handleAddToDo}/> );};
Select which component properties should be adjusted dynamically, such as button texts or headers depending on whether a To-Do is being created or edited. Define properties such as label
and submitText
to reflect correct actions depending on the operation the user wants to perform.
const EditToDoPage = ({ allId }) => { const navigate = useNavigate(); const handleEditToDo = () => { // Logic for editing To-Do // Then redirect to home navigate('/'); };
return ( <ToDoForm label="Edit your To-Do" submitText="Edit" onSubmit={handleEditToDo}/> );};
Implementing these best practices will not only help keep your code clean and efficient, but will also provide a superior user experience by simplifying navigation through paths rather than using complicated portals. Keep exploring and improving your skills, constant practice is the key to web development mastery.
Contributions 12
Questions 3
umm, mi lado radical eliminó todo lo que tenía delineado amarillo, pero mi lado prudente hizo commit antes de eso.
👀 Yo cree un div que encierre o agrupe el formulario para poder centrarlo, ya que si lo hacemos de la forma normal con el margin auto, en responsive se rompe un poco la ui
const NewPage = () => {
return (
<div className='new-todo-container'>
<TodoForm
title="Write your new TODO"
submitText="Add"
submitEvent={() => console.log('llamar a add todo')}
/>
</div>
)
}
Y el css
.new-todo-container{
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
Espero les sirva.
Saludos.
Una alternativa a la funcionalidad creada en la clase para los textos dinamicos, es usar el hook de React Router DOM ‘useLocation’ que devuelve la ruta actualmente usada y con esto hacer la validación necesaria.
Creo que así, nos evitamos el tener que mandar props adicionales.
const location = useLocation();
<label>{(location.pathname === '/new') ? 'Escribe tu TODO' : 'Edita tu TODO'}</label>
Yo el botón de CreateTodo lo cambiaría por un componente Link.
Esto dice la documentación 👇:
Además, un componente Link es una etiqueta <a href=""> por detrás, lo cual es necesario para tener un buen SEO.
.
Es el equivalente a usar un <button> en vez de un <a> para cambiar de URLs en HTML puro.
Estaba pensando otra manera que se podría hacer es que al agregar tareas, en lugar de navegar a una página de Edit o New Todo, se añada un nuevo input al final de los todos y deshabilitar su uso modificación hasta que se haga click en Edit.
Me pasó que justo cuando hice los cambios con el profe no tenía TODOS para confirmar si lo que hice estaba bien, así que tuve que hacer por adelantado el añadir TODOS (Aunque no sé si es la mejor forma, me funcionó)
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 TO DO"
submit="Añadir"
submitEvent={addTodo}
/>
)
}
export { NewTodoPage }
Hola papus, dejo el codigo de la clase en TS:
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 }
sería bueno haber dejado el modal como para no perder la funcionalidad de los portales y hacer el edit en una nueva ventana
.
Vamos a eliminar los modales y portales de la aplicación para utilizar rutas en su lugar.
.
En el componente HomePage
comentamos todo lo relacionado a modales y portales, importamos useNavigate
y guardamos su llamado en una constante navigate
.
.
Al renderizar los todos en la render prop onEdit
usamos la navegación para dirigirnos a /edit/:id
donde id
será el ID del TODO.
.
Finalmente, el botón de crear TODOs recibirá una función flecha que por medio de navegación nos dirige a /new
.
.
...
import { useNavigate } from 'react-router-dom';
...
function HomePage() {
const navigate = useNavigate();
...
const {
...
// openModal,
...
} = state;
const {
// setOpenModal,
// addTodo,
...
} = stateUpdaters;
return (
...
{todo => (
<TodoItem
key={todo.id}
text={todo.text}
completed={todo.completed}
onEdit={() => navigate('/edit/' + todo.id)}
onComplete={() => completeTodo(todo.id)}
onDelete={() => deleteTodo(todo.id)}
/>
)}
...
{/* {!!openModal && (
<Modal>
<TodoForm
addTodo={addTodo}
setOpenModal={setOpenModal}
/>
</Modal>
)} */}
<CreateTodoButton
onClick={() => navigate('/new')}
// setOpenModal={setOpenModal}
/>
...
);
}
export { HomePage };
.
En el componente CreateTodoButton
ya no necesitamos modales, por lo que solo le enviamos la función que pasamos por props a la propiedad onClick
.
.
import React from 'react';
import './CreateTodoButton.css';
function CreateTodoButton(props) {
return (
<button
className="CreateTodoButton"
onClick={props.onClick}
>
+
</button>
);
}
export { CreateTodoButton };
.
En el componente TodoForm
necesitamos que sea dinámico, tanto para editar, como para crear TODOs.
.
Lo que cambia es que ahora utilizamos navegación tanto para el botón de Cancelar
como para el botón para realizar el Submit
, vamos redirigir hacia /
. Además nuestra función onSubmit
va a utilizar una función que pasaremos por props submitEvent
que será versátil para crear o editar TODOs según sea el caso.
.
Finalmente, tanto el label
como el texto del botón de submit
van a ser dinámicos y los pasaremos por props.
.
...
import { useNavigate } from 'react-router-dom';
...
function TodoForm(props) {
const navigate = useNavigate();
...
const onCancel = () => {
navigate('/');
};
const onSubmit = (event) => {
event.preventDefault();
navigate('/');
props.submitEvent(newTodoValue);
};
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 };
.
Desde el archivo TodoForm.css
centramos el componente y le quitamos el color de fondo que tenía en la clase form
.
.
form {
width: 90%;
max-width: 300px;
/* background-color: #fff; */
margin: 0 auto;
padding: 33px 40px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.
Por último, solo que modificar los componentes de EditTodoPage
y NewTodoPage
de la siguiente manera.
.
import React from 'react';
import { TodoForm } from '../../ui/TodoForm';
function EditTodoPage() {
return (
<TodoForm
label="Edita tu TODO"
submitText="Editar"
submitEvent={() => console.log('Llamar a editTodo')}
/>
);
}
export { EditTodoPage };
import React from 'react';
import { TodoForm } from '../../ui/TodoForm';
function NewTodoPage() {
return (
<TodoForm
label="Escribe tu nuevo TODO"
submitText="Añadir"
submitEvent={() => console.log('Llamar a addTodo')}
/>
);
}
export { NewTodoPage };
Want to see more contributions, questions and answers from the community?