Ich muss einige Geschäftslogik abhängig vom Browserverlauf implementieren.
Was ich tun möchte, ist ungefähr so:
reactRouter.onUrlChange(url => {
this.history.Push(url);
});
Gibt es eine Möglichkeit, einen Rückruf vom reaktionsrouter zu erhalten, wenn die URL aktualisiert wird?
Sie können die Funktion history.listen()
verwenden, wenn Sie versuchen, die Routenänderung zu erkennen. Wenn Sie annehmen, dass Sie react-router v4
Verwenden, verpacken Sie Ihre Komponente mit withRouter
HOC, um Zugriff auf die Stütze history
zu erhalten.
history.listen()
gibt eine unlisten
-Funktion zurück. Sie würden dies verwenden, um unregister
vom Hören abzuhalten.
Sie können Ihre Routen wie folgt konfigurieren
index.js
ReactDOM.render(
<BrowserRouter>
<AppContainer>
<Route exact path="/" Component={...} />
<Route exact path="/Home" Component={...} />
</AppContainer>
</BrowserRouter>,
document.getElementById('root')
);
und dann in AppContainer.js
class App extends Component {
componentWillMount() {
this.unlisten = this.props.history.listen((location, action) => {
console.log("on route change");
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<div>{this.props.children}</div>
);
}
}
export default withRouter(App);
Aus der Geschichte docs :
Mit
history.listen
Können Sie nach Änderungen am aktuellen Standort suchen:history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) })
Das location-Objekt implementiert eine Teilmenge der window.location-Schnittstelle, einschließlich:
**location.pathname** - The path of the URL **location.search** - The URL query string **location.hash** - The URL hash fragment
Standorte können auch die folgenden Eigenschaften aufweisen:
location.state - Ein zusätzlicher Status für diesen Speicherort, der sich nicht in der URL befindet (unterstützt in
createBrowserHistory
undcreateMemoryHistory
)
location.key
- Eine eindeutige Zeichenfolge, die diesen Speicherort darstellt (unterstützt increateBrowserHistory
undcreateMemoryHistory
)Die Aktion ist eine von
Push, REPLACE, or POP
, Abhängig davon, wie der Benutzer zur aktuellen URL gelangt ist.
Wenn Sie den React-Router v3 verwenden, können Sie history.listen()
aus dem history
-Paket verwenden, wie oben erwähnt, oder Sie können auch browserHistory.listen()
verwenden.
Sie können Ihre Routen wie folgt konfigurieren und verwenden
import {browserHistory} from 'react-router';
class App extends React.Component {
componentDidMount() {
this.unlisten = browserHistory.listen( location => {
console.log('route changes');
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<Route path="/" onChange={yourHandler} component={AppContainer}>
<IndexRoute component={StaticContainer} />
<Route path="/a" component={ContainerA} />
<Route path="/b" component={ContainerB} />
</Route>
)
}
}
Wenn Sie das Objekt history
global abhören möchten, müssen Sie es selbst erstellen und an Router
übergeben. Dann können Sie es mit der listen()
-Methode anhören:
// Use Router from react-router, not BrowserRouter.
import { Router } from 'react-router';
// Create history object.
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
// Listen to history changes.
// You can unlisten by calling the constant (`unlisten()`).
const unlisten = history.listen((location, action) => {
console.log(action, location.pathname, location.state);
});
// Pass history to Router.
<Router history={history}>
...
</Router>
Noch besser ist es, wenn Sie das Verlaufsobjekt als Modul erstellen, sodass Sie es problemlos überall dort importieren können, wo Sie es benötigen (z. B. import history from './history';
Ich bin auf diese Frage gestoßen, als ich versucht habe, den ChromeVox-Bildschirmleser auf den oberen Rand des "Bildschirms" zu fokussieren, nachdem ich in einer React einseitigen App zu einem neuen Bildschirm navigiert habe. Grundsätzlich habe ich versucht, was zu emulieren Dies würde passieren, wenn diese Seite geladen würde, indem Sie einem Link zu einer neuen, vom Server gerenderten Webseite folgen.
Für diese Lösung sind keine Listener erforderlich. Sie verwendet withRouter()
und die componentDidUpdate()
-Lebenszyklusmethode, um einen Klick auszulösen, mit dem ChromeVox beim Navigieren zu einem neuen URL-Pfad auf das gewünschte Element fokussiert wird.
Ich habe eine "Screen" -Komponente erstellt, die um das React-Router-Switch-Tag gewickelt ist, das alle Apps-Bildschirme enthält.
<Screen>
<Switch>
... add <Route> for each screen here...
</Switch>
</Screen>
Screen.tsx
KomponenteHinweis: Diese Komponente verwendet React + TypeScript
import React from 'react'
import { RouteComponentProps, withRouter } from 'react-router'
class Screen extends React.Component<RouteComponentProps> {
public screen = React.createRef<HTMLDivElement>()
public componentDidUpdate = (prevProps: RouteComponentProps) => {
if (this.props.location.pathname !== prevProps.location.pathname) {
// Hack: setTimeout delays click until end of current
// event loop to ensure new screen has mounted.
window.setTimeout(() => {
this.screen.current!.click()
}, 0)
}
}
public render() {
return <div ref={this.screen}>{this.props.children}</div>
}
}
export default withRouter(Screen)
Ich habe versucht, focus()
anstelle von click()
zu verwenden, aber durch Klicken auf wird ChromeVox angehalten, was gerade gelesen wird, und es wird erneut an der Stelle begonnen, an der ich es anweisen soll.
Hinweis für Fortgeschrittene: In dieser Lösung wird die Navigation <nav>
, Die innerhalb der Screen-Komponente und nach dem Inhalt <main>
Gerendert wird, visuell über dem main
positioniert CSS order: -1;
. Also im Pseudocode:
<Screen style={{ display: 'flex' }}>
<main>
<nav style={{ order: -1 }}>
<Screen>
Wenn Sie Gedanken, Kommentare oder Tipps zu dieser Lösung haben, fügen Sie bitte einen Kommentar hinzu.