Logotipo de Zephyrnet

React Router v5: la guía completa

Fecha:

Reaccionar enrutador es la biblioteca de enrutamiento estándar de facto para React. Cuando necesite navegar a través de una aplicación React con múltiples vistas, necesitará un enrutador para administrar las URL. React Router se encarga de eso, manteniendo la interfaz de usuario de la aplicación y la URL sincronizadas.

Este tutorial le presenta React Router v5 y muchas cosas que puede hacer con él.

Introducción

React es una biblioteca popular para crear aplicaciones de una sola página (SPA) que se representan en el lado del cliente. Un SPA puede tener múltiples vistas (también llamado paginas), y a diferencia de las aplicaciones convencionales de varias páginas, navegar por estas vistas no debería hacer que se vuelva a cargar toda la página. En cambio, queremos que las vistas se representen en línea dentro de la página actual. El usuario final, que está acostumbrado a las aplicaciones de varias páginas, espera que las siguientes características estén presentes en un SPA:

  • Cada vista en una aplicación debe tener una URL que especifique de manera única esa vista. Esto es para que el usuario pueda marcar la URL como referencia en otro momento. Por ejemplo, www.example.com/products.
  • El botón de avance y retroceso del navegador debería funcionar como se esperaba.
  • Las vistas anidadas generadas dinámicamente también deberían tener una URL propia. Por ejemplo, example.com/products/shoes/101, donde 101 es la identificación del producto.

enrutamiento es el proceso de mantener sincronizada la URL del navegador con lo que se muestra en la página. React Router te permite manejar el enrutamiento declarativamente. El enfoque de enrutamiento declarativo le permite controlar el flujo de datos en su aplicación, diciendo "la ruta debería verse así":

<Route path="/about" component={About} />

Puedes colocar tu <Route> componente en cualquier lugar donde desee que se represente su ruta. Ya que <Route>, <Link> y todas las otras API de React Router con las que trataremos son solo componentes, puede acostumbrarse fácilmente al enrutamiento en React.

Una nota antes de comenzar. Existe una idea errónea de que React Router es una solución de enrutamiento oficial desarrollada por Facebook. En realidad, es una biblioteca de terceros que es muy popular por su diseño y simplicidad. Si sus requisitos se limitan a enrutadores para la navegación, puede implementar un enrutador personalizado desde cero sin mucha molestia. Sin embargo, comprender cómo los conceptos básicos de React Router le brindarán una mejor perspectiva de cómo debería funcionar un enrutador.

General

Este tutorial está dividido en diferentes secciones. Primero, configuraremos React y React Router usando npm. Luego saltaremos directamente a lo básico de React Router. Encontrará diferentes demostraciones de código de React Router en acción. Los ejemplos cubiertos en este tutorial incluyen:

  1. enrutamiento básico de navegación
  2. enrutamiento anidado
  3. enrutamiento anidado con parámetros de ruta
  4. enrutamiento protegido

Todos los conceptos relacionados con la construcción de estas rutas se discutirán en el camino. El código completo del proyecto está disponible en este repositorio de GitHub. Una vez que esté dentro de un directorio de demostración en particular, ejecute npm install instalar las dependencias Para servir la aplicación en un servidor de desarrollo, ejecute npm start y dirígete a http://localhost:3000/ para ver la demo en acción.

¡Vamos a empezar!

Configuración de React Router

Supongo que ya tiene un entorno de desarrollo en funcionamiento. Si no, dirígete a "Comenzando con React y JSX". Alternativamente, puedes usar Crear aplicación React para generar los archivos necesarios para crear un proyecto básico de React. Esta es la estructura de directorios predeterminada generada por la aplicación Create React:

 react-router-demo ├── .gitignore ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json ├── README.md ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ └── registerServiceWorker.js └── yarn.lock

La biblioteca React Router consta de tres paquetes: react-router, react-router-domy react-router-native. react-router es el paquete principal para el enrutador, mientras que los otros dos son específicos del entorno. Deberías usar react-router-dom si está creando un sitio web y react-router-native si estás en un entorno de desarrollo de aplicaciones móviles usando React Native.

Use npm para instalar react-router-dom:

npm install --save react-router-dom

Conceptos básicos de React Router

Aquí hay un ejemplo de cómo se verán nuestras rutas:

<Router>/* App component */
class App extends React.Component { render() { return ( <div> <nav className="navbar navbar-light"> <ul className="nav navbar-nav"> /* Link components are used for linking to other views */ <li> <Link to="/">Homes</Link> </li> <li> <Link to="/category">Category</Link> </li> <li> <Link to="/products">Products</Link> </li> </ul> </nav> /* Route components are rendered if the path prop matches the current URL*/ <Route path="/" component={Home} /> <Route path="/category" component={Category} /> <Route path="/products" component={Products} /> </div> ); }
} <Route exact path="/" component={Home} /> <Route path="/category" component={Category} /> <Route path="/login" component={Login} /> <Route path="/products" component={Products} />
</Router>

Router

Necesita un componente de enrutador y varios componentes de ruta para configurar una ruta básica como se ejemplificó anteriormente. Como estamos creando una aplicación basada en navegador, podemos usar dos tipos de enrutadores de la API React Router:

  1. <BrowserRouter>
  2. <HashRouter>

La principal diferencia entre ellos es evidente en las URL que crean:

// <BrowserRouter>
http://example.com/about // <HashRouter>
http://example.com/#/about

El proyecto <BrowserRouter> es más popular entre los dos porque usa la API de historial HTML5 para realizar un seguimiento del historial de su enrutador. los <HashRouter>, por otro lado, usa la parte hash de la URL (window.location.hash) para recordar cosas. Si tiene la intención de admitir navegadores heredados, debe seguir con <HashRouter>.

Envolver el <BrowserRouter> componente alrededor del componente de la aplicación.

index.js

/* Import statements */
import React from "react";
import ReactDOM from "react-dom"; /* App is the entry point to the React code.*/
import App from "./App"; /* import BrowserRouter from 'react-router-dom' */
import { BrowserRouter } from "react-router-dom"; ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, document.getElementById("root")
);

Nota: Un componente de enrutador solo puede tener un único elemento hijo. El elemento secundario puede ser un elemento HTML, como div, o un componente de reacción.

Para que funcione el React Router, debe importar la API relevante desde react-router-dom biblioteca. Aquí he importado el BrowserRouter dentro index.js. También importé el App componente de App.js. App.js, como habrás adivinado, es el punto de entrada a los componentes React.

El código anterior crea una instancia de historial para todo nuestro componente de la aplicación. Déjame presentarte formalmente la historia.

historia

history es una biblioteca de JavaScript que le permite administrar fácilmente el historial de sesiones en cualquier lugar donde se ejecute JavaScript. history proporciona una API mínima que le permite administrar la pila del historial, navegar, confirmar la navegación y mantener el estado entre sesiones. - Documentos de entrenamiento de React

Cada componente del enrutador crea un objeto de historial que realiza un seguimiento de la ubicación actual (history.location) y también las ubicaciones anteriores en una pila. Cuando cambia la ubicación actual, la vista se vuelve a representar y se obtiene una sensación de navegación. ¿Cómo cambia la ubicación actual? El objeto de historial tiene métodos como history.push() y history.replace() para cuidar de eso history.push() se invoca cuando hace clic en un <Link> componente y history.replace() se llama cuando usas <Redirect>. Otros métodos, como history.goBack() y history.goForward() - se utilizan para navegar a través de la pila del historial al retroceder o avanzar una página.

Continuando, tenemos enlaces y rutas.

Enlaces y Rutas

El proyecto <Route> El componente es el componente más importante en el enrutador React. Representa alguna interfaz de usuario si la ubicación actual coincide con la ruta de la ruta. Idealmente, un <Route> componente debe tener un accesorio llamado path, y si el nombre de ruta coincide con la ubicación actual, se representa.

El proyecto <Link> componente, por otro lado, se utiliza para navegar entre páginas. Es comparable al elemento de anclaje HTML. Sin embargo, el uso de enlaces de anclaje daría lugar a una actualización del navegador, lo que no queremos. Entonces, en cambio, podemos usar <Link> para navegar a una URL en particular y volver a representar la vista sin una actualización del navegador.

Hemos cubierto todo lo que necesita saber para crear un enrutador básico. Construyamos uno.

Demostración 1: enrutamiento básico

src / App.js

/* Import statements */
import React, { Component } from "react";
import { Link, Route, Switch } from "react-router-dom"; /* Home component */
const Home = () => ( <div> <h2>Home</h2> </div>
); /* Category component */
const Category = () => ( <div> <h2>Category</h2> </div>
); /* Products component */
const Products = () => ( <div> <h2>Products</h2> </div>
); export default function App() { return ( <div> <nav className="navbar navbar-light"> <ul className="nav navbar-nav"> <li> <Link to="/">Homes</Link> </li> <li> <Link to="/category">Category</Link> </li> <li> <Link to="/products">Products</Link> </li> </ul> </nav> /* Route components are rendered if the path prop matches the current URL */ <Route path="/" component={Home} /> <Route path="/category" component={Category} /> <Route path="/products" component={Products} /> </div> );
}

Hemos declarado los componentes para el hogar, la categoría y los productos dentro App.js. Aunque esto está bien por ahora, cuando el componente comienza a crecer, es mejor tener un archivo separado para cada componente. Como regla general, generalmente creo un nuevo archivo para un componente si ocupa más de 10 líneas de código. A partir de la segunda demostración, crearé un archivo separado para los componentes que han crecido demasiado para caber dentro del App.js archivo.

Dentro del componente de la aplicación, hemos escrito la lógica para el enrutamiento. los <Route>La ruta de acceso coincide con la ubicación actual y se representa un componente. El componente que se debe representar se pasa como un segundo accesorio.

Aquí / coincide con ambos / y /category. Por lo tanto, ambas rutas coinciden y se representan. ¿Cómo evitamos eso? Deberías pasar el exact= {true} accesorios para el enrutador con path='/':

<Route exact={true} path="/" component={Home} />

Si desea que se represente una ruta solo si las rutas son exactamente las mismas, debe usar los accesorios exactos.

Enrutamiento anidado

Para crear rutas anidadas, necesitamos tener una mejor comprensión de cómo <Route> trabajos. Vamos a hacer eso.

<Route> tiene tres accesorios que puedes usar para definir lo que se renderiza:

  • componente. Ya hemos visto esto en acción. Cuando la URL coincide, el enrutador crea un elemento React del componente dado usando React.createElement.
  • ceder. Esto es útil para la representación en línea. El accesorio de renderizado espera una función que devuelve un elemento cuando la ubicación coincide con la ruta de la ruta.
  • niños. El elemento secundario es similar a render en que espera una función que devuelve un elemento React. Sin embargo, los elementos secundarios se representan independientemente de si la ruta coincide o no con la ubicación.

Camino y partido

El proyecto camino se usa para identificar la parte de la URL que debe coincidir con el enrutador. Utiliza la biblioteca Path-to-RegExp para convertir una cadena de ruta en una expresión regular. Luego se comparará con la ubicación actual.

Si la ruta del enrutador y la ubicación coinciden correctamente, se crea un objeto y lo llamamos partido objeto. El objeto de coincidencia contiene más información sobre la URL y la ruta. Se puede acceder a esta información a través de sus propiedades, que se enumeran a continuación:

  • match.url. Una cadena que devuelve la parte coincidente de la URL. Esto es particularmente útil para construir anidadas <Link>s
  • match.path. Una cadena que devuelve la cadena de ruta de la ruta, es decir, <Route path="">. Usaremos esto para construir anidados <Route>s.
  • match.isExact. Un booleano que devuelve verdadero si la coincidencia fue exacta (sin caracteres finales).
  • match.params. Un objeto que contiene pares clave / valor de la URL analizada por el paquete Path-to-RegExp.

Ahora que sabemos todo sobre <Route>s, construyamos un enrutador con rutas anidadas.

Componente de interruptor

Antes de dirigirnos al código de demostración, quiero presentarles el <Switch> componente. Cuando es múltiple <Route>s se usan juntos, todas las rutas que coinciden se representan de manera inclusiva. Considere este código de la demostración 1. He agregado una nueva ruta para demostrar por qué <Switch> es útil:

<Route exact path="/" component={Home}/>
<Route path="/products" component={Products}/>
<Route path="/category" component={Category}/>
<Route path="/:id" render = {()=> (<p> I want this text to show up for all routes other than '/', '/products' and '/category' </p>)}/>

Si la URL es /products, todas las rutas que coinciden con la ubicación /products son prestados. Entonces el <Route> con camino :id se procesa junto con el Products componente. Esto es por diseño. Sin embargo, si este no es el comportamiento que espera, debe agregar el <Switch> componente a sus rutas. Con <Switch>, solo el primer hijo <Route> que coincide con la ubicación se procesa.

Demostración 2: enrutamiento anidado

Anteriormente, creamos rutas para /, /category y /products. ¿Qué pasaría si quisiéramos una URL del formulario? /category/shoes?

src / App.js

import React, { Component } from "react";
import { Link, Route, Switch } from "react-router-dom";
import Category from "./Category"; export default function App() { return ( <div> <nav className="navbar navbar-light"> <ul className="nav navbar-nav"> <li> <Link to="/">Homes</Link> </li> <li> <Link to="/category">Category</Link> </li> <li> <Link to="/products">Products</Link> </li> </ul> </nav> <Switch> <Route exact path="/" component={Home} /> <Route path="/category" component={Category} /> <Route path="/products" component={Products} /> </Switch> </div> );
} /* Code for Home and Products component omitted for brevity */

A diferencia de la versión anterior de React Router, en la versión 4 y siguientes, el anidado <Route>s debe ir preferiblemente dentro del componente padre. Es decir, el componente Categoría es el principal aquí, y declararemos las rutas para category/:name dentro del componente padre.

src / Category.jsx

import React from "react";
import { Link, Route } from "react-router-dom"; const Category = ({ match }) => { return ( <div> {" "} <ul> <li> <Link to={`${match.url}/shoes`}>Shoes</Link> </li> <li> <Link to={`${match.url}/boots`}>Boots</Link> </li> <li> <Link to={`${match.url}/footwear`}>Footwear</Link> </li> </ul> <Route path={`${match.path}/:name`} render={({ match }) => ( <div> {" "} <h3> {match.params.name} </h3> </div> )} /> </div> );
};
export default Category;

Primero, hemos declarado un par de enlaces para las rutas anidadas. Como se menciono antes, match.url se utilizará para construir enlaces anidados y match.path para rutas anidadas. Si tienes problemas para entender el concepto de partido, console.log(match) proporciona información útil que podría ayudar a aclararlo.

<Route path={`${match.path}/:name`} render={({ match }) => ( <div> <h3> {match.params.name} </h3> </div> )}
/>

Este es nuestro primer intento de enrutamiento dinámico. En lugar de codificar las rutas, hemos usado una variable dentro del nombre de ruta. :name es un parámetro de ruta y captura todo después category/ hasta que se encuentre otra barra diagonal. Entonces, un nombre de ruta como products/running-shoes creará un params objetar de la siguiente manera:

{ name: "running-shoes";
}

Los datos capturados deben estar accesibles en match.params or props.match.params dependiendo de cómo se pasan los accesorios. La otra cosa interesante es que hemos usado un render apuntalar. render Los accesorios son bastante útiles para las funciones en línea que no requieren un componente propio.

Demostración 3: enrutamiento anidado con parámetros de ruta

Vamos a complicar un poco más las cosas, ¿de acuerdo? Un enrutador del mundo real tendrá que lidiar con los datos y mostrarlos dinámicamente. Supongamos que tenemos los datos del producto devueltos por una API de servidor del siguiente formulario.

src / Products.jsx

const productData = [ { id: 1, name: "NIKE Liteforce Blue Sneakers", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin molestie.", status: "Available", }, { id: 2, name: "Stylised Flip Flops and Slippers", description: "Mauris finibus, massa eu tempor volutpat, magna dolor euismod dolor.", status: "Out of Stock", }, { id: 3, name: "ADIDAS Adispree Running Shoes", description: "Maecenas condimentum porttitor auctor. Maecenas viverra fringilla felis, eu pretium.", status: "Available", }, { id: 4, name: "ADIDAS Mid Sneakers", description: "Ut hendrerit venenatis lacus, vel lacinia ipsum fermentum vel. Cras.", status: "Out of Stock", },
];

Necesitamos crear rutas para los siguientes caminos:

  • /products. Esto debería mostrar una lista de productos.
  • /products/:productId. Si un producto con el :productId existe, debe mostrar los datos del producto, y si no, debe mostrar un mensaje de error.

src / Products.jsx

/* Import statements have been left out for code brevity */ const Products = ({ match }) => { const productsData = [ { id: 1, name: "NIKE Liteforce Blue Sneakers", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin molestie.", status: "Available", }, //Rest of the data has been left out for code brevity ]; /* Create an array of `<li>` items for each product */ const linkList = productsData.map((product) => { return ( <li> <Link to={`${match.url}/${product.id}`}>{product.name}</Link> </li> ); }); return ( <div> <div> <div> <h3> Products</h3> <ul> {linkList} </ul> </div> </div> <Route path={`${match.url}/:productId`} render={(props) => <Product data={productsData} {...props} />} /> <Route exact path={match.url} render={() => <div>Please select a product.</div>} /> </div> );
};

Primero, creamos una lista de <Links>s usando el productsData.ids y lo almacenó en linkList. La ruta toma un parámetro en la cadena de ruta que corresponde al del ID del producto.

<Route path={`${match.url}/:productId`} render={(props) => <Product data={productsData} {...props} />}
/>

Puedes haber esperado component = { Product } en lugar de la función de renderizado en línea. El problema es que necesitamos transmitir productsData al componente Producto junto con todos los accesorios existentes. Aunque hay otras maneras de hacerlo, creo que este método es el más fácil. {...props} usa ES6 sintaxis extendida para pasar todo el objeto de utilería al componente.

Aquí está el código para el componente del producto.

src / Product.jsx

/* Import statements have been left out for code brevity */ const Product = ({ match, data }) => { var product = data.find(p => p.id == match.params.productId); var productData; if (product) productData = ( <div> <h3> {product.name} </h3> <p>{product.description}</p> <hr /> <h4>{product.status}</h4>{" "} </div> ); else productData = <h2> Sorry. Product doesn't exist </h2>; return ( <div> <div>{productData}</div> </div> );
};

El proyecto find El método se utiliza para buscar en la matriz un objeto con una propiedad ID que sea igual a match.params.productId. Si el producto existe, el productData se visualiza. Si no, se muestra el mensaje "El producto no existe".

Protegiendo rutas

Para la demostración final, discutiremos técnicas relacionadas con la protección de rutas. Entonces, si alguien intenta acceder /admin, tendrían que iniciar sesión primero. Sin embargo, hay algunas cosas que debemos cubrir antes de poder proteger las rutas.

Redireccionar

Al igual que las redirecciones del lado del servidor, <Redirect> reemplazará la ubicación actual en la pila de historial con una nueva ubicación. La nueva ubicación está especificada por el to apuntalar. Así es como usaremos <Redirect>:

<Redirect to={{pathname: '/login', state: {from: props.location}}}

Entonces, si alguien intenta acceder al /admin mientras esté desconectado, serán redirigidos a /login ruta. La información sobre la ubicación actual se pasa por estado, de modo que si la autenticación es exitosa, el usuario puede ser redirigido a la ubicación original. Dentro del componente secundario, puede acceder a esta información en this.props.location.state.

Rutas personalizadas

Una ruta personalizada es una palabra elegante para una ruta anidada dentro de un componente. Si necesitamos tomar una decisión sobre si una ruta debe ser representada o no, escribir una ruta personalizada es el camino a seguir. Aquí está la ruta personalizada declarada entre otras rutas.

src / App.js

/* Add the PrivateRoute component to the existing Routes */
<nav className="navbar navbar-light"> <ul className="nav navbar-nav"> ... <li><Link to="/admin">Admin area</Link></li> </ul>
</nav> <Switch> <Route exact path="/" component={Home} data={data} /> <Route path="/category" component={Category} /> <Route path="/login" component={Login} /> <PrivateRoute path="/admin" component={Admin} /> <Route path="/products" component={Products} />
</Switch>

fakeAuth.isAuthenticated devuelve verdadero si el usuario ha iniciado sesión y falso en caso contrario.

Aquí está la definición de PrivateRoute:

src / App.js

/* PrivateRoute component definition */
const PrivateRoute = ({ component: Component, ...rest }) => { return ( <Route {...rest} render={props => fakeAuth.isAuthenticated === true ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: "/login", state: { from: props.location } }} /> ) } /> );
};

La ruta representa el componente Admin si el usuario ha iniciado sesión. De lo contrario, el usuario es redirigido a /login. Lo bueno de este enfoque es que es evidentemente más declarativo y PrivateRoute Es reutilizable.

Finalmente, aquí está el código para el componente Iniciar sesión:

src / Login.jsx

import React, { useState } from "react";
import { Redirect } from "react-router-dom"; export default function Login(props) { const { from } = props.location.state || { from: { pathname: "/" } }; console.log(from); const [redirectToReferrer, setRedirectToReferrer] = useState(false); const login = () => { fakeAuth.authenticate(() => { setRedirectToReferrer(true); }); }; if (redirectToReferrer) { return <Redirect to={from} />; } return ( <div> <p>You must log in to view the page at {from.pathname}</p> <button onClick={login}>Log in</button> </div> );
} /* A fake authentication function */
export const fakeAuth = { isAuthenticated: false, authenticate(cb) { this.isAuthenticated = true; setTimeout(cb, 100); }
};

La siguiente línea muestra desestructuración de objetos, que forma parte de la especificación ES6:

const { from } = this.props.location.state || { from: { pathname: "/" } };

Encajemos las piezas del rompecabezas, ¿de acuerdo? Aquí está la demostración final de la aplicación que creamos usando el enrutador React.

Demostración 4: Protección de rutas

Resumen

Como has visto en este artículo, React Router es una biblioteca poderosa que complementa React para construir mejores rutas declarativas. A diferencia de las versiones anteriores de React Router, en v5, todo es "solo componentes". Además, el nuevo patrón de diseño encaja perfectamente en la forma React de hacer las cosas.

En este tutorial, aprendimos:

  • cómo configurar e instalar React Router
  • Los fundamentos del enrutamiento y algunos componentes esenciales como <Router>, <Route> y <Link>
  • Cómo crear un enrutador mínimo para la navegación y rutas anidadas
  • Cómo construir rutas dinámicas con parámetros de ruta

Finalmente, aprendimos algunas técnicas avanzadas de enrutamiento para crear la demostración final de rutas protegidas.

Fuente: https://www.sitepoint.com/react-router-complete-guide/?utm_source=rss

punto_img

Información más reciente

punto_img