react-router: ¿Cómo actualizo la URL sin causar una navegación/recarga?

4 minutos de lectura

Con el enrutador de reacción, he hecho esto para actualizar la URL:

this.props.history.push({
            pathname: `/product/${this.props.product.id}`,
        });

Sin embargo, esto provoca un cambio de renderizado/navegación. ¿Hay alguna manera de actualizar la URL sin hacer eso?

Mi caso de uso es que tengo una lista de productos y cuando hago clic en uno, muestro un Modal y quiero actualizar la URL a algo como ejemplo.com/producto/1 para que el enlace se pueda compartir.

No pude encontrar una solución usando React Router, pero pude lograr esto usando la interfaz de historial del navegador llamando:

window.history.replaceState(null, "New Page Title", "/pathname/goes/here")

Puedes aprender más sobre .replaceState aquí.

Reaccionar del enrutador history.replace no siempre funcionará

Reaccionar del enrutador history.replace El método puede activar o no una nueva representación dependiendo de la configuración de la ruta de su aplicación (por ejemplo, tiene un catch-all /* ruta). No impide un renderizado por definición.

  • Tenga en cuenta que este cambio podría pasar por alto el conocimiento de React Router de la ruta actual si se vuelve a modificar más tarde. Por ejemplo, si agrega 1 subruta usando este método y luego usa RR para navegar hacia arriba 1 nivel, saltará visualmente 2 porque RR aún cree que la ubicación no tiene la subruta adjunta.

    – Toro Magnus

    26 de enero de 2021 a las 10:13

  • Tuve exactamente el mismo problema que el OP y lo resolví usando su enfoque. ¡Muchas gracias! @MagnusBull para el historial del navegador, simplemente uso window.history.pushState(stringify(currentParams), ""); y eso parece funcionar, aunque no he encontrado el problema de la ruta secundaria del que hablaste

    – Sangeet Agarwal

    15 de marzo de 2021 a las 17:48


  • @ usr28765526 ​​Mi punto es que si usa React Router para manejar la navegación, entonces usa la API del navegador replaceState puede considerarse un “hackeo” y RR no sabrá que la ruta cambió. Si intenta usar React Router’s location una vez modificada la URL, operará sobre la versión de la URL que conoce: La anterior al cambio. Esto puede ser impredecible y confuso.

    – Toro Magnus

    16 de marzo de 2021 a las 18:37

  • ¡Muy útil, gracias! No sabía que history.replace podría causar re-renderizaciones

    – Katie Fedoseeva

    26/09/2022 a las 23:50

Avatar de usuario de AngelSalazar
AngelSalazar

reemplazar anulará la URL

this.props.history.replace({ pathname: `/product/${this.props.product.id}`})

  • Eso definitivamente todavía hace que el enrutador actúe, y luego hay una pantalla en blanco (supongo que no puede encontrar una ruta)

    – peculiaridades extrañas

    18 de julio de 2019 a las 20:15

  • realmente, reemplazar solo debe anular la URL

    – Ángel Salazar

    18 de julio de 2019 a las 20:22

  • Encontré esto que funciona: window.history.replaceState(null, null, /product/${this.props.product.id});

    – peculiaridades extrañas

    18 de julio de 2019 a las 20:23

  • react-router replace debería comportarse como replaceState. Puedo confirmar que replace no activa un renderizado, consulte esta pequeña demostración jsbin.com/jinazirowa/edit?html,js,salida

    – Ángel Salazar

    18 de julio de 2019 a las 20:26


  • Esto debería funcionar sin actualizar/renderizar, siempre que la ruta del enrutador encapsule la nueva ruta.

    – Toro Magnus

    26 de enero de 2021 a las 10:09

Avatar de usuario de Nivek Mozart
nivek mozart

Estoy usando una buena forma de engañar a los usuarios: la URL no cambia.

Para hacer esto, solo necesitará configurar sus rutas de esta manera.

const Home="https://stackoverflow.com/";
const About="https://stackoverflow.com/";
const Contact="https://stackoverflow.com/";

Fíjate en los espacios. Todos los caracteres se contarán dentro de la cita, por lo que debería funcionar.

Routes.tsx

<Route exact path={Home} component={Home} />
<Route exact path={About} component={About} />
<Route exact path={Contact} component={Contact} />

dentro de tu About.tsx y Contact.tsx:

  useEffect(() => {
    window.history.replaceState(null, '', Home);
  }, []);

Después de que el usuario navega a About o Contact páginas, se llamará al gancho y se ejecutará el código dentro de la función de devolución de llamada. Eliminará los espacios después de que el componente se renderice.

Ese debería ser un truco limpio para disfrazar la URL oculta 😂

Cuando estás dentro de un componente de reacción, el props posee historypuedes usar eso.

Para aquellos que buscan una forma de navegar incluso cuando no están dentro de un componente de reacción, es decir, no pueden obtener el props.historyEsta es un forma de hacerlo:

En el componente donde representa el enrutador:

// outside the component
export const browserRouterRef = React.createRef();

// on render
<BrowserRouter ref={browserRouterRef}>

Entonces puedes importar browserRouterRef en cualquier lugar y uso browserRouterRef.current.history para cambiar la ruta incluso si no está dentro de un componente de reacción.

¿Ha sido útil esta solución?