React router zmienia adres URL, ale nie wyświetla


87

Mam problem ze zmianą widoku w odpowiedzi na routing. Chcę tylko pokazać listę użytkowników, a kliknięcie każdego użytkownika powinno prowadzić do strony szczegółów. Oto router:

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'))

Kiedy używam adresu URL / szczegółów, moja przeglądarka przechodzi do tego adresu URL, ale nie zmienia widoku. Każda inna trasa zgłasza 404, więc wydaje się, że rozpoznaje trasę, ale nie aktualizuje.


Otrzymuję dwa błędy: jeden z informacją, że używanie właściwości proptypes z głównego pakietu reagowania jest przestarzałe. Dwa stwierdzenia przy użyciu React.createClass są przestarzałe. Myślałem, że to nie ma związku, ponieważ kod działa bez użycia routingu.
MARyan87

Czy Twój komponent jest prawidłowo zamontowany?
Jeremy John

Odpowiedzi:


74

Musisz określić atrybut exactdla swojego indexRoute, w przeciwnym razie dla /detailstrasy równej będzie on nadal pasował /. Spróbuj także importować Routezreact-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'))

AKTUALIZACJA:

Inną rzeczą, którą musisz zrobić, jest dołączenie użytkowników komponentu withRouter. Musisz używać withRoutertylko wtedy, gdy twój komponent nie otrzymuje Router props,

Może się to zdarzyć w przypadkach, gdy twój komponent jest zagnieżdżonym dzieckiem komponentu renderowanego przez router lub nie przekazałeś do niego właściwości routera lub gdy komponent nie jest w ogóle połączony z routerem i jest renderowany jako oddzielny komponent z Trasy.

W Users.js dodaj

import {withRouter} from 'react-router';

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

DOCS


ostrzeżenie proptypes można usunąć, instalując npm install -S 'prop-types'i zastępując React.PropsTypes atrybutem PropTypes. Również zaktualizować package.json skorzystać z najnowszych pakowane od innych pakietów może być jeszcze za pomocą React.PropTypes i React.createClass
Shubham Khatri

Również czy próbujesz ponownie załadować stronę po zmianie adresu URL, aby zobaczyć, czy się ładuje
Shubham Khatri

Spróbowałem przeładować stronę, nie zmienia to widoku.
Ładuje

2
Czy możesz wypróbować zaktualizowaną odpowiedź z Routeimportem z „React-router-dom” zamiastreact-router
Shubham Khatri

Jeśli nie został jeszcze rozwiązany, powiąż komponent użytkownika withRouter, pomógł mi rozwiązać ten sam problem wcześniej. Daj mi znać. Zaktualizowałem też kod.
Shubham Khatri

27

Musisz tylko owinąć komponenty wewnątrz routera .

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

Oto przykładowy plik App.js:

...
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;

Dodatkowy

Jeśli używasz routera reagującego, składnik componentWillReceiveProps zostanie wywołany za każdym razem, gdy zmieni się adres URL.

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

Uwaga

Alternatywnie, możesz również opakować komponent w Router przed eksportem, ale wtedy musisz zadbać o kilka innych rzeczy. Zwykle pomijam ten krok.

export default withRouter(Profile)

3
<Route exact path = "/ mypath" component = {withRouter (MyComponent)} /> działał dla mnie
Santosh Kumar

16

Miałem ten sam problem i odkryłem, że to dlatego, że miałem zagnieżdżony router. Po usunięciu zagnieżdżonego routera i po prostu umieszczeniu tras specyficznych dla komponentu w komponencie przełącznika - problem został rozwiązany bez konieczności korzystania z routera withRouter lub wprowadzania jakichkolwiek dodatkowych zmian.

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

Yusufbek opisuje podobny problem. Myślę, że przechowywanie tras związanych z komponentami na poziomie widoku jest dużo czystsze niż przechowywanie ich wszystkich na jednym głównym routerze. W aplikacji produkcyjnej będzie to o wiele za dużo tras, aby można było łatwo czytać i debugować problemy.


Używam aplikacji create-react- i to zadziałało. To prawda, że ​​zbudowałem konfigurację routera zgodnie z samouczkiem na youtube, więc aplikacja create-react-app może nie być powiązana.
Dustin English

14

Napotkałem ten sam problem, ale go naprawiłem. Stronę główną umieściłem jako ostatnią. Mi to pasuje. Tak jak poniżej.

    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'))


5
Korzystanie z tej exactwłaściwości rozwiązałoby również ten problem.
isherwood

8

Podczas korzystania z Redux i ja miałem podobne problemy, w których adres URL aktualizował się na pasku adresu, ale aplikacja nie ładowała odpowiedniego komponentu. Udało mi się rozwiązać, dodając withRouter do eksportu:

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

export default withRouter(connect(mapStateToProps)(MyComponentName))

7

Miałem podobny problem, ale z inną strukturą. Dodałem jeden router, który będzie obsługiwał wszystkie trasy, użyłem komponentu Switch do przełączania widoków. Ale w rzeczywistości tak się nie stało. Zmieniono tylko adres URL, ale nie wyświetlono. Powodem tego był komponent Link używany wewnątrz komponentu SideBar, który znajdował się poza komponentem Router. (Tak, wyeksportowałem SideBar z „withRouter”, nie działało). Tak więc rozwiązaniem było przeniesienie mojego komponentu SideBar, który zawiera wszystkie komponenty Link do mojego routera.

Problem tkwi w moich linkerach, są one poza moim routerem

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

Rozwiązaniem było przeniesienie moich linkerów do routera

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

3
pomaganie sobie uczyniło mój dzień. Próbowałem tego z dwoma oddzielnymi routerami. Jeden znajdował się w pasku nawigacyjnym, a drugi w ciele, aby pomieścić komponent. Teraz umieściłem wszystko w tym samym routerze w komponencie nadrzędnym i wszystko działa tak, jak powinno.
Matteus Barbosa

3
Doskonale - mój dokładny problem. Dziękuję
Geoffrey Bourne

2
Dzięki! Uratowałeś mnie!!
AzizStark

1
Próbowałem wszystkiego, w tym withRouter, ale tylko to rozwiązanie zadziałało ... trochę wyjaśnienia byłoby pomocne, aby zrozumieć, dlaczego tak się dzieje
Jim,

1
@Jim myślę reagować-Router używa kontekstowego API i <Router />aka <BrowserRouter /> zapewnia kontekst do dopasowujących trasy jak <Route />, <Switch /> i elementów nawigacyjnych <Link />, <Redirect />. Aby zapewnić ten sam kontekst, należy opakować wszystkie komponenty podrzędne w ramach dostawcy kontekstu, którym jest <Router />.
Yusufbek


5

BrowserRouter nie przechowuje historii w Twoim przypadku. Zamiast tego użyj "routera", użyj tego z niestandardową historią, ponieważ rekwizyty mogą pomóc rozwiązać problem.

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;

Następnie w swoich komponentach zaimportuj customHistory z „aplikacji” i użyj tego do nawigacji.

customHistory.push('/pathname');

Mam nadzieję, że to pomoże! :)


1
nie ma potrzeby exactatrybut gdy używaszSwitch
KBT

4

Musisz dodać dokładne do trasy indeksu i zamiast zamykać te trasy komponenty przez div, użyj opcji Switch fromreak-router-dom do przełączania się między trasami.

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'))

3

Miałem podobny problem z React Router w wersji 4:

Klikając <Link />komponent, URL zmieniłby się, ale widoki nie.

Używał jednego z widoków PureComponent a nie Component(importował react) i to było przyczyną.

Zastąpiłem wszystkie komponenty renderowane przez trasę, które były używane PureComponentdo Component, mój problem został rozwiązany.

(Źródło rozdzielczości: https://github.com/ReactTraining/react-router/issues/4975#issuecomment-355393785 )


1
Dzięki. To naprawiło to dla mnie. Ale to był tylko komponent zawierający Switch, który musiałem rozszerzyć z Component zamiast PureComponent, aby zmiana widoku na żywo działała.
Christiaan Westerbeek

1
Zmieniłem mój czysty komponent na komponent, ale to nie działa dla mnie.
Kosalram Rama Krishnan

2

Miałem podobny problem, który rozwiązałem, aby polubić ten, spójrz, mam nadzieję, że działa.

Musisz użyć funkcji componentWillReceiveProps w swoim komponencie.

kliknięto łącze po raz pierwszy, wywołując adres url www.example.com/content1/ componentDidMount () jest uruchamiany.

Teraz, kiedy klikniesz inny link, powiedz, że www.example.com/content2/ ten sam komponent jest wywoływany, ale tym razem zmienia się prop i możesz uzyskać dostęp do tej nowej właściwości pod componentWillReceiveProps (nextProps), której możesz użyć do wywołania API Lub pozostaw stan pusty i pobierz nowy dane.

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

1

Hmm, nie ma żadnego przełącznika, który faktycznie przełączałby widoki.

w ten sposób używam routera do przełączania się ze strony głównej na stronę główną

//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, znalazłem, że używasz innego routera ... przepraszam, to może te skrzypce będą dla Ciebie przydatne

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

być może klucz rozwiązania jest ukryty w linii dla głównej funkcji renderowania.

Router.run(routes, function(Handler) {
    React.render(<Handler />, document.getElementById('container'));
});

1

Mam ten sam problem. Nie sądzę, żeby w tym przypadku musiał dodać prop z routerem, po prostu sprawdź w swoim NavLink, czy jako szczegóły wpisujesz dobrą nazwę ścieżki. jeśli chodzi o trasę, spróbuj zacząć od określonej trasy do ogólnej, takiej jak

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

w twoim NavLink powinno być mniej więcej tak

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

Przypomnijmy, że importowanie lepiej zacząć od zaimportowania wszystkich rzeczy związanych z Reactem, po czym zaimportuj drugi moduł, taki jak ten:

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";

przyjdź w ten sposób:

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";

1

Dla mnie miałem:

export MyClass extends React.Component

z:

export default withRouter(MyClass)

W międzyczasie w moim App.js miałem:

import { MyClass } from './MyClass'

Osoby grające w grę domową mogą zobaczyć mój problem. Nie otrzymałem importu z routerem przekazanym do klas podrzędnych. Aby to uporządkować, przeniosłem wywołanie withRouter do deklaracji komponentu Route:

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

W MyClass zmieniłem go na domyślny eksport:

export default MyClass extends React.Component

I wreszcie w App.js zmieniłem import na:

import MyClass from './MyClass'

Mam nadzieję, że to komuś pomoże. Zapewnia to, że nie miałem dwóch sposobów eksportowania tej samej klasy, pomijając w ten sposób przedrostek withRouter .


0

Spróbuj tego,

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'))

Zdefiniuj komponent Wrapper, który będzie renderował this.props.children. To będzie przebiegać prawidłowo.
Vaibhav Singh


0

Miałem podobny problem z układem warunkowym:

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

i przepisałem warunki w ten sposób:

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

To rozwiązało problem. W moim przypadku wydaje się, że kontekst został utracony.


0

W moim przypadku przejście na HashRouter zamiast BrowserRouter rozwiązało mój problem


0

Miałem ten sam problem i naprawiłem go, importując historię z folderu @types w node_modules. Zaimportowałem go z npm (npm i @history)


0

Ja też miałem ten sam problem. Chociaż nie jest to bardzo skuteczne rozwiązanie, rozwiązałem je sprytną metodą. Metoda ComponentDidMount działa za każdym razem, gdy zmienia się nasz adres URL. W ramach metody możemy porównać poprzedni adres URL z aktualnym adresem URL oraz zmienić stan lub odświeżyć stronę.

componentDidUpdate(prevProps) {
    if (this.props.match.url !== prevProps.match.url) {
        //this.props.history.go(0) refresh Page
        //this.setState(...) or change state
    }
}

-1

Ja też napotkałem kłopoty.

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

Wypróbowałem rozwiązania zaproponowane przez Shubhama Khatri, ale to nie działa.


Rozwiązałem ten problem, może mogę ci pomóc.

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

Według powyższego dokumentu przewodnik podczas korzystania PureComponentlub korzystania z narzędzi do zarządzania stanem podoba redux, mobx... To może zablokować aktualizację swojej trasie. Sprawdź komponent trasy, upewnij się, że nie zablokowałeś zwrotu komponentu.


-2

spróbuj dodać prop forceRefresh = {true} do BrowserRouter (routera)

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

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

mi to pasuje.

przy okazji to nie jest prawdziwe rozwiązanie: D

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.