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.
reactjs
react-router
MARyan87
źródło
źródło
Odpowiedzi:
Musisz określić atrybut
exact
dla swojego indexRoute, w przeciwnym razie dla/details
trasy równej będzie on nadal pasował/
. Spróbuj także importowaćRoute
zreact-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ćwithRouter
tylko wtedy, gdy twój komponent nie otrzymujeRouter 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
źródło
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.createClassRoute
importem z „React-router-dom” zamiastreact-router
withRouter
, pomógł mi rozwiązać ten sam problem wcześniej. Daj mi znać. Zaktualizowałem też kod.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)
źródło
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.
źródło
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'))
źródło
exact
właściwości rozwiązałoby również ten problem.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))
źródło
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>
źródło
<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 />
.W moim przypadku omyłkowo zagnieździłem dwa
BrowserRouter
s.źródło
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! :)
źródło
exact
atrybut gdy używaszSwitch
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'))
źródło
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 nieComponent
(importowałreact
) i to było przyczyną.Zastąpiłem wszystkie komponenty renderowane przez trasę, które były używane
PureComponent
doComponent
, mój problem został rozwiązany.(Źródło rozdzielczości: https://github.com/ReactTraining/react-router/issues/4975#issuecomment-355393785 )
źródło
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 }
źródło
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')); });
źródło
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";
źródło
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 .
źródło
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'))
źródło
Powinieneś to sprawdzić: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md
Dlatego na pewno nie jest
Users
lubDetails
, ponieważ są one renderowane bezpośrednio przez<Route>
ilocation
zostaną przekazaneprops
.Zastanawiam się, dlaczego potrzebujesz
<div>
między<BrowserRouter>
i<Route>
? Usuń to i daj mi znać, czy działa.źródło
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.
źródło
W moim przypadku przejście na HashRouter zamiast BrowserRouter rozwiązało mój problem
źródło
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)
źródło
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 } }
źródło
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
PureComponent
lub korzystania z narzędzi do zarządzania stanem podobaredux
,mobx
... To może zablokować aktualizację swojej trasie. Sprawdź komponent trasy, upewnij się, że nie zablokowałeś zwrotu komponentu.źródło
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
źródło