React router

El módulo react router nos va a permitir navegar por las distintas páginas de nuestra aplicación React. Cuando utilizamos un enlace programado con react router la url del navegador cambiará, sin embargo, la página no se refrescará en su totalidad; sólo serán cargados los componentes correspondientes a la nueva url.

Dicho de otra forma, react router nos permite cargar unos componentes u otros en función de la url.

npm i react-router-dom

Documentación de react-router

Configuración básica

src/app/Router.js
import { BrowserRouter, Route, Routes} from 'react-router-dom';
import Home from '../pages/Home';
import Page2 from '../pages/Page2';

const Router = () => (
    <BrowserRouter>
        <Routes>   
            <Route index element={<Home/>} />
            <Route path="/page2/" element={<Page2/>} />
             { /* Es muy recomendable añadir esta ruta para obtener un mensaje de error en el caso de que la ruta no exista. De lo contrario, si la ruta no existe llegaremos a una página en blanco */}    
            <Route path="*" element={<div>404</div> } />
        </Routes>
    </BrowserRouter>
);

export default Router;

Para recuperar el valor del parámetro id, podemos hacer un console log de las props en la página destino y ahí veremos la propiedad match, en la que estará el valor.

src/App.js
import Router from './app/Router';

export default () => <Routes />;
src/pages/Home.js
import { Link } from 'react-router-dom';

const NavBar= () => 
    <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/page2">Page2</Link></li>
        <li><Link to="/ajksdfkjhasdk">Error en la url</Link></li>
    </ul>;

export default NavBar;

Si deseas resaltar el enlace correspondiente a la página en la que estás, puedes usar la etiqueta NavLink, que añade el class active a dicho enlace.

import { NavLink } from 'react-router-dom';

const NavBar= () => 
    <ul>
        <li><NavLink to="/">Home</NavLink></li>
        <li><NavLink to="/page2">Page2</NavLink></li>
        <li><NavLink to="/ajksdfkjhasdk">Error en la url</NavLink></li>
    </ul>;

export default NavBar;

Recogida de parámetros

Recoger un parámetro de React Router

En el enlace:

<Link to="/product/1">Producto 1</Link>

En el Router.js:

<Route path="/product/:id" element={<Product/>} />

En el fichero en el que queremos recoger los datos:

import { useParams } from 'react-router-dom';
...
const { id } = useParams();

Recoger un parámetro del tipo ?param=valor&…

En la página en la queremos recuperar parámetros de la url, usaremos el siguiente código:

import { useLocation } from "react-router-dom";
...
const query = new URLSearchParams(useLocation().search);
  • useLocation().search accede a los parámetros de la url en la que estamos
  • URLSearchParams alimenta el objeto query, que usaremos para acceder a los parámetros mediante getters y setters.

A partir de aquí, cuando querramos recuperar los parámetros de la url:

const questionId = query.get('questionId');

Redirección desde React

Definimos el método que ejecutará la redirección:

import { useNavigate } from "react-router-dom";

const App = () => {
    const navigate = useNavigate();

    const pulsado = () => {
        navigate(process.env.PUBLIC_URL+'/page2');
    }

    return(  
            <button onClick={pulsado}>Pulsame</button>
    )
}
export default App;

Rutas para cuando el proyecto no está en la raíz del servidor

.env

PUBLIC_URL = "/amor"

Router.js

<BrowserRouter>
  <Routes>
    <Route path={process.env.PUBLIC_URL}>
      <Route index element={<Home />} />
      <Route path="page2" element={<Page2 />} />
    </Route>
  </Routes>
</BrowserRouter>
src/pages/Home.js
import { Link } from 'react-router-dom';

const NavBar = () => 
    <ul>
        <li><Link to={process.env.PUBLIC_URL}>Inicio</Link></li>
        <li><Link to={process.env.PUBLIC_URL + "/page2"}>Page2</Link></li>
        <li><Link to={process.env.PUBLIC_URL + "/ajksdfkjhasdk"}>Error en la url</Link></li>
    </ul>;

export default NavBar;

Para no tener que repetir constantemente process.env.PUBLIC_URL en todas las urls, podríamos crear este componente:

import {Link as NavLink} from "react-router-dom";

const Link = ({to, ...props}) => <NavLink {...props} to={process.env.PUBLIC_URL + to} />;

export default Link;

Configurar un Layout

import { BrowserRouter, Route, Routes} from 'react-router-dom';
import Home from '../pages/Home';
import Page2 from '../pages/Page2';

const Router = () => (
    <BrowserRouter>
        <Routes>
            <Route element={<Layout/>}>
                <Route path="/" element={<Home/>} />
                <Route path="/page2/" element={<Page2/>} />
                <Route path="*" element={<div>404</div> } />
            </Route>
        </Routes>
    </BrowserRouter>
);

export default Router;

Layout.js

Utilizaremos Outlet para cargar el contenido del Router.

import { Link, Outlet } from 'react-router-dom';

const Layout= () => (
    <div>
        <div className='navbar'>
            <ul>
                <li><Link to="/">Home</Link></li>
                <li><Link to="/page2">Page2</Link></li>
            </ul>
        </div>
        <Outlet />
    </div>
)

export default Layout;

Configuración del fichero .htaccess para evitar errores 404 al refrescar la página

Guardaremos un fichero .htaccess en la carpeta de la aplicación de React que estamos desarrollando.

# Front-controller (exclude static resources)
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule . index.html [L]

Enrutar a un enrutamiento

No olvidar, poner la barra con el asterisco en la ruta que enlaza al enrutamiento.

<Route path="swapi/*" element={<Swapi/>} />

No será necesario repetir toda la ruta en el enrutamiento de destino. Para el menú que lleva a la home de este enrutamiento, podemos usar la prop index, en lugar de path=»/».

const Router = () => (
  <Routes>
    <Route index element={<Home/>}/>
    <Route path="profile" element={<Profile/>}/>
    <Route path="*" element={<div>404 Swapi</div>}/>
  </Routes>
);
← Aplicación para hacer deporte
useEffect →