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.