閲覧履歴に応じていくつかのビジネスロジックを実装する必要があります。
私がやりたいのはこのようなものです:
reactRouter.onUrlChange(url => {
this.history.Push(url);
});
URLが更新されたときにreact-routerからコールバックを受信する方法はありますか?
ルートの変更を検出しようとするときに history.listen()
関数を使用できます。 react-router v4
を使用していることを考慮し、コンポーネントをwithRouter
HOCでラップして、history
プロパティにアクセスします。
history.listen()
はunlisten
関数を返します。 unregister
を聞いてこれを使用します。
次のようなルートを設定できます
index.js
ReactDOM.render(
<BrowserRouter>
<AppContainer>
<Route exact path="/" Component={...} />
<Route exact path="/Home" Component={...} />
</AppContainer>
</BrowserRouter>,
document.getElementById('root')
);
そして、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);
履歴から docs :
history.listen
を使用して、現在の場所への変更をリッスンできます。history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) })
ロケーションオブジェクトは、次を含むwindow.locationインターフェイスのサブセットを実装します。
**location.pathname** - The path of the URL **location.search** - The URL query string **location.hash** - The URL hash fragment
ロケーションには次のプロパティもあります。
location.state-URLに存在しないこの場所の追加の状態(
createBrowserHistory
およびcreateMemoryHistory
でサポート)
location.key
-この場所を表す一意の文字列(createBrowserHistory
およびcreateMemoryHistory
でサポート)アクションは、ユーザーが現在のURLにアクセスした方法に応じて、
Push, REPLACE, or POP
のいずれかです。
反応ルーターv3を使用している場合、上記のhistory
パッケージのhistory.listen()
を使用するか、browserHistory.listen()
を使用することもできます。
次のようなルートを設定して使用できます
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>
)
}
}
history
オブジェクトをグローバルにリッスンする場合は、自分で作成してRouter
に渡す必要があります。次に、listen()
メソッドでそれを聞くことができます:
// 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>
履歴オブジェクトをモジュールとして作成すると、必要に応じて簡単にインポートできます(例:import history from './history';
Reactシングルページアプリで新しい画面に移動した後、ChromeVoxスクリーンリーダーを「画面」の上部にフォーカスしようとしていたときにこの質問に出会いました。基本的に、新しいサーバーレンダリングされたWebページへのリンクをたどって、このページが読み込まれた場合に何が起こるかをエミュレートしようとしています。
このソリューションはリスナーを必要としません。新しいURLパスに移動するときに、withRouter()
およびcomponentDidUpdate()
ライフサイクルメソッドを使用してクリックをトリガーし、目的の要素にChromeVoxをフォーカスします。
すべてのアプリ画面を含む反応ルータースイッチタグを囲む「スクリーン」コンポーネントを作成しました。
<Screen>
<Switch>
... add <Route> for each screen here...
</Switch>
</Screen>
Screen.tsx
コンポーネント注:このコンポーネントは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)
focus()
の代わりにclick()
を使用しようとしましたが、クリックすると、ChromeVoxは現在読んでいるものの読み取りを停止し、開始するように指示した場所から再開します。
高度な注意:このソリューションでは、Screenコンポーネント内で<nav>
コンテンツの後にレンダリングされるナビゲーション<main>
は、css order: -1;
を使用してmain
の上に視覚的に配置されます。擬似コードで:
<Screen style={{ display: 'flex' }}>
<main>
<nav style={{ order: -1 }}>
<Screen>
このソリューションに関するご意見、コメント、またはヒントがある場合は、コメントを追加してください。