Reaccionar el enrutador cambia la URL pero no ver

82

Tengo problemas para cambiar la vista al reaccionar con el enrutamiento. Solo quiero mostrar una lista de usuarios, y al hacer clic en cada usuario, debo navegar a una página de detalles. Aquí está el enrutador:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from 'react-router-dom';
import Users from "./components/Users";
import { Router, Route } from "react-router";
import Details from "./components/Details";

ReactDOM.render((
  <BrowserRouter>
    <div>
        <Route path="/" component={Users} />
        <Route path="/details" component={Details} />
    </div>
  </BrowserRouter>
), document.getElementById('app'))

Cuando utilizo la URL / detalles, mi navegador navega a esa URL, pero no cambia la vista. Cualquier otra ruta arroja 404, por lo que parece reconocer la ruta pero no actualizarla.

MARyan87
fuente
Recibo dos errores: uno que indica que el uso de proptypes del paquete principal de reacción está en desuso. Dos que indican el uso de React.createClass están en desuso. Pensé que esto no estaba relacionado, ya que el código funciona sin usar enrutamiento.
MARyan87
¿Su componente está montando correctamente?
Jeremy John

Respuestas:

70

exactDebe especificar el atributo para su indexRoute, de lo contrario /details, aún coincidirá con la ruta uniforme /. También intente importar Routedesdereact-router-dom

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from 'react-router-dom';
import Users from "./components/Users";

import Details from "./components/Details";

ReactDOM.render((
  <BrowserRouter>
    <div>
        <Route exact path="/" component={Users} />
        <Route path="/details" component={Details} />
    </div>
  </BrowserRouter>
), document.getElementById('app'))

ACTUALIZAR:

Otra cosa que debe hacer es adjuntar los usuarios de su componente withRouter. Solo debe utilizarlo withRoutercuando su componente no reciba el Router props,

Esto puede suceder en los casos en que su componente es un elemento secundario anidado de un componente renderizado por el enrutador o no le ha pasado los accesorios del enrutador o cuando el componente no está vinculado al enrutador en absoluto y se representa como un componente separado de las Rutas.

En Users.js agregue

import {withRouter} from 'react-router';

.........
export default withRouter(Users)

DOCS

Shubham Khatri
fuente
La advertencia de proptypes se puede eliminar instalando npm install -S 'prop-types'y reemplazando React.PropsTypes con PropTypes. También actualice su package.json para hacer uso del último paquete, ya que otros paquetes pueden seguir usando React.PropTypes y React.createClass
Shubham Khatri
Además, ¿intenta volver a cargar la página cuando la URL cambia para ver si se carga?
Shubham Khatri
Intenté recargar la página, no cambia la vista. Se carga en la vista Usuarios incluso si la url es / # / details
MARyan87
1
¿Puede probar la respuesta actualizada con Routeimportado de 'react-router-dom` en lugar dereact-router
Shubham Khatri
Si aún no se ha resuelto, vincule el componente de usuario con withRouter, me ha ayudado a resolver el mismo problema antes. Házmelo saber. También he actualizado el código.
Shubham Khatri
27

Solo tienes que envolver los componentes dentro con Router .

<Route exact path="/mypath" component={withRouter(MyComponent)} />

Aquí hay un archivo App.js de muestra:

...
import { BrowserRouter as Router, Route, Switch, withRouter } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";

class App extends Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/" component={withRouter(Home)} />
          <Route exact path="/profile" component={withRouter(Profile)} />
        </Switch>
      </Router>
    );
  }
}

export default App;

Adicional

Si está utilizando el enrutador react, se llamará a componentWillReceiveProps cada vez que cambie la URL.

componentWillReceiveProps(nextProps) {
    var currentProductId = nextProps.match.params.productId;
    var nextProductId = nextProps.match.params.productId; // from the new url
    ...
}

Nota

Alternativamente, también puede envolver el componente con Router antes de exportar, pero luego debe asegurarse de algunas otras cosas. Normalmente me salto este paso.

export default withRouter(Profile)
Elementos de codificación
fuente
3
<Route exact path = "/ mypath" component = {withRouter (MyComponent)} /> funcionó para mí
Santosh Kumar
14

Tuve el mismo problema y descubrí que era porque tenía un enrutador anidado. Una vez que eliminé el enrutador anidado y simplemente puse las rutas específicas de mi componente dentro de un componente de conmutador, el problema se resolvió sin tener que usar con el enrutador o realizar cambios adicionales.

<Router> // <--Remove nested Router
    <Switch>
      <Route exact path="/workflows" component={ViewWorkflows} />
      <Route path="/workflows/new" component={NewWorkflow} />
    </Switch>
</Router>

Yusufbek describe un problema similar. Creo que es mucho más limpio almacenar las rutas relacionadas con los componentes a nivel de vista en lugar de almacenarlas todas en un enrutador principal. En una aplicación de producción, serán demasiadas rutas para leer y depurar problemas fácilmente.

Ryan Brockhoff
fuente
13

Me he enfrentado al mismo problema pero lo solucioné. He colocado la página de inicio como última. Esto funciona para mi. Como a continuación.

    import React from "react";
    import ReactDOM from "react-dom";
    import { BrowserRouter } from 'react-router-dom';
    import Users from "./components/Users";
    import { Router, Route } from "react-router";
    import Details from "./components/Details";

    ReactDOM.render((
      <BrowserRouter>
        <div>
            <Route path="/details" component={Details} />
            <Route path="/" component={Users} />
        </div>
      </BrowserRouter>
    ), document.getElementById('app'))

Shahab Khan
fuente
5
El uso de la exactpropiedad también lo habría resuelto.
Isherwood
Sí, tiene usted razón.
Shahab Khan hace
8

Al usar Redux y tuve problemas similares en los que la URL se actualizaba en la barra de direcciones, pero la aplicación no cargaba el componente respectivo. Pude resolver agregando withRouter a la exportación:

import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'

export default withRouter(connect(mapStateToProps)(MyComponentName))
Bruce Seymour
fuente
5

Tuve un problema similar pero con una estructura diferente. Agregué un enrutador que manejará todas las rutas, usé el componente Switch para cambiar de vista. Pero en realidad no fue así. Solo la URL cambió, pero no la vista. La razón de esto fue el componente Link utilizado dentro del componente SideBar que estaba fuera del componente Router. (Sí, he exportado SideBar con "withRouter", no funcionó). Entonces, la solución fue mover mi componente SideBar que contiene todos los componentes Link a mi enrutador.

El problema está en mis enlazadores, están fuera de mi enrutador

<div className="_wrapper">
  <SideBar /> // Holds my all linkers
  <Router>
     <Switch>
       <Route path="/" component={Home} />
       <Route path="/users" component={Users} />
     </Switch>
  </Router>
 </div>

La solución fue mover mis enlazadores a mi enrutador

<div className="_wrapper">
  <Router>
     <SideBar /> // Holds my all linkers
     <Switch>
       <Route path="/" component={Home} />
       <Route path="/users" component={Users} />
     </Switch>
  </Router>
</div>
Yusufbek
fuente
2
Servirme a ti mismo hizo mi día. Lo estaba intentando con dos enrutadores separados. Uno estaba dentro de la barra de navegación y otro dentro del cuerpo para acomodar el componente. Ahora pongo todo dentro del mismo enrutador en el componente principal y las cosas funcionan como deberían.
Matteus Barbosa
3
Excelente, mi problema exacto. Gracias
Geoffrey Bourne
2
¡Gracias! ¡¡Me salvaste!!
AzizStark
5

En mi caso, había anidado por error dos BrowserRouters.

Karuhanga
fuente
5

BrowserRouter no puede mantener el historial en su caso. Utilice "Enrutador" en su lugar. El uso de este con un historial personalizado como accesorios puede ayudar a resolver su problema.

import {Router, Route, Switch, withRouter } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import {createBrowserHistory} from 'history';

export const customHistory = createBrowserHistory();  //This maintains custom history

class App extends Component {
  render() {
    return (
      <Router history={customHistory}>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route exact path="/profile" component={Profile} />
        </Switch>
      </Router>
    );
  }
}

export default App;

Luego, en sus componentes, importe customHistory desde 'App' y utilícelo para navegar.

customHistory.push('/pathname');

¡Espero que esto ayude! :)

Anglesvar Cheenu
fuente
1
no es necesario el exactatributo cuando lo usaSwitch
KBT
4

Debe agregar exacto a la ruta del índice y, en lugar de incluir esos componentes de ruta por div, use Cambiar de react-router-dom para cambiar entre las rutas.

import React from "react";
import ReactDOM from "react-dom";
import { Route, Switch } from 'react-router-dom';
import Users from "./components/Users";

import Details from "./components/Details";

ReactDOM.render((
  <div>
    <Switch>
        <Route path="/" component={Users} exact/>
        <Route path="/details" component={Details} />
    </Switch>
  </div>
), document.getElementById('app'))
Vinay J Rao
fuente
3

Tuve un problema similar con React Router versión 4:

Al hacer clic en el <Link />componente, la URL cambiaría pero las vistas no.

Una de las vistas estaba usando en PureComponentlugar de Component(importada de react) y esa fue la causa.

Mediante la sustitución de todos los componentes de la ruta dictada que estaban utilizando PureComponenta Component, se resolvió mi problema.

(Fuente de resolución: https://github.com/ReactTraining/react-router/issues/4975#issuecomment-355393785 )

Kunok
fuente
1
Gracias. Eso me lo arregló. Pero fue solo el componente que contenía Switch que tuve que extender desde Component en lugar de PureComponent para que el cambio de vista en vivo funcione.
Christiaan Westerbeek
He cambiado mi componente puro a componente, aunque no me funciona.
Kosalram Rama Krishnan
1

Hmm, no hay ningún INTERRUPTOR para cambiar de vista.

así es como uso el enrutador para cambiar de la página de aterrizaje al sitio principal

//index.jsx    
ReactDOM.render( (<BrowserRouter><App/></BrowserRouter>), document.getElementById('root') );


//App.jsx
render()
{
    return <div>
        <Switch>
            <Route exact path='/' component={Lander}/>
            <Route path='/vadatajs' component={Vadatajs}/>
        </Switch>
    </div>
}

https://jsfiddle.net/Martins_Abilevs/4jko7arp/11/

ups, encontré que usas un enrutador diferente ... lo siento, entonces tal vez este violín sea útil para ti

https://fiddle.jshell.net/terda12/mana88Lm/

tal vez la clave de la solución esté oculta en línea para la función principal de renderizado.

Router.run(routes, function(Handler) {
    React.render(<Handler />, document.getElementById('container'));
});
Martín Abilev
fuente
1

Estaba enfrentando un problema similar que resolví como este, por favor, eche un vistazo, espero que esté funcionando.

Debe utilizar la función componentWillReceiveProps en su componente.

hizo clic en un enlace por primera vez llamando a la URL www.example.com/content1/ se ejecuta componenteDidMount ().

Ahora, cuando haga clic en otro enlace, diga www.example.com/content2/ se llama al mismo componente, pero esta vez el prop cambia y puede acceder a este nuevo prop en componentWillReceiveProps (nextProps) que puede usar para llamar a API O dejar el estado en blanco y obtener nuevo datos.

componentWillReceiveProps(nextProps){
     //call your API and update state with new props
}
Sanat Gupta
fuente
1

Para mi, tuve:

export MyClass extends React.Component

con:

export default withRouter(MyClass)

Mientras tanto, en mi App.js, tuve:

import { MyClass } from './MyClass'

Los que juegan en casa pueden ver mi problema. No estaba obteniendo la importación con el enrutador pasado a las clases secundarias. Para limpiar esto, moví la llamada withRouter a la declaración del componente Route:

<Router exact path={'/myclass'} component={withRouter(MyClass)} />

De vuelta en MyClass, lo cambié a una exportación predeterminada:

export default MyClass extends React.Component

Y luego, finalmente, en App.js, cambié mi importación a:

import MyClass from './MyClass'

Ojalá esto ayude a alguien. Esto asegura que no tuviera dos formas de exportar la misma clase, evitando así el prefijo withRouter .

Codenova
fuente
0

Prueba esto,

import React from "react";

import ReactDOM from "react-dom";
import Users from "./components/Users";
import { Router, Route } from "react-router";


import Details from "./components/Details";

ReactDOM.render((
  <Router>
        <Route path="/" component={Wrapper} >
            <IndexRoute component={Users} />
            <Route path="/details" component={Details} />
        </Route>
  </Router>
), document.getElementById('app'))
Vaibhav Singh
fuente
Defina un componente Wrapper que renderizará this.props.children. Esto se enrutará correctamente.
Vaibhav Singh
0

Tuve un problema similar con un diseño condicional:

class LayoutSwitcher extends Component {
  render () {
    const isLoggedIn = this.props.isLoggedIn
    return (
      <React.Fragment>
        { isLoggedIn
          ? <MainLayout {...this.props} />
          : <Login />
        }
      </React.Fragment>
    )
  }
}

y reescribió las condiciones así:

  render () {
    const isLoggedIn = this.props.isLoggedIn
    if (isLoggedIn) {
      return <MainLayout {...this.props} />
    }
    return <Login />
  }

Esto lo solucionó. En mi caso, parece que se perdió el contexto.

sym
fuente
0

Tengo el mismo problema. No creo que en este caso necesite agregar el prop withRouter, solo verifique en su NavLink que escriba el nombre de la ruta correcta como detalles. para la ruta intente comenzar desde la ruta específica a la general como

<Route path="/details" component={Details} />
<Route path="/" component={Users} />

en su NavLink debería ser algo como esto

 <NavLink className="nav-link" to="/details">
   details<span className="sr-only">(current)</span>
 </NavLink>

un comentario para la importación, es mejor comenzar importando todo lo relacionado con React después de importar el otro módulo como este:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from 'react-router-dom';
import Users from "./components/Users";
import { Router, Route } from "react-router";
import Details from "./components/Details";

ven así:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from 'react-router-dom';
import { Router, Route } from "react-router";

import Users from "./components/Users";    
import Details from "./components/Details";
KBT
fuente
0

En mi caso, cambiar a HashRouter en lugar de BrowserRouter resolvió mi problema

lloyd agola
fuente
0

Tuve el mismo problema y lo solucioné al importar el historial de la carpeta @types en node_modules. Lo importé de npm (npm i @history)

Nico
fuente
-1

Yo también encontré problemas.

https://github.com/chengjianhua/templated-operating-system

Y probé las soluciones mencionadas por Shubham Khatri, pero no funciona.


Resolví este problema, tal vez pueda ayudarte.

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md

De acuerdo con el documento de guía anterior, cuando usa PureComponento usa con herramientas de administración de estado como redux, mobx... Puede bloquear la actualización de su ruta. Verifique el componente de su ruta, asegúrese de no bloquear la reproducción de su componente.

Jianhua Cheng
fuente
-2

intente agregar prop forceRefresh = {true} a BrowserRouter (enrutador)

import {BrowserRouter as Router} from "react-router-dom";

<Router forceRefresh={true}>
/// your <switch> and <route>
</Router>

esto funciona para mi.

por cierto no es una solución real: D

Oarkon
fuente