mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 10:17:55 +02:00
fix(v2): normalize location for route matching (#2393)
* fix(v2): normalize location path for route matching * fix(v2): Memoize normalized pathnames * fix(v2): fix wrong reference to this.state instead of normalized location * Update normalizeLocation.js Co-authored-by: Yangshun Tay <tay.yang.shun@gmail.com>
This commit is contained in:
parent
c05cb75cbc
commit
a0570e48ac
3 changed files with 114 additions and 6 deletions
|
@ -11,6 +11,7 @@ import nprogress from 'nprogress';
|
|||
|
||||
import clientLifecyclesDispatcher from './client-lifecycles-dispatcher';
|
||||
import preload from './preload';
|
||||
import normalizeLocation from './normalizeLocation';
|
||||
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
|
@ -37,19 +38,20 @@ class PendingNavigation extends React.Component {
|
|||
// If `routeDidChange` is true, means the router is trying to navigate to a new
|
||||
// route. We will preload the new route.
|
||||
if (routeDidChange) {
|
||||
const nextLocation = normalizeLocation(nextProps.location);
|
||||
this.startProgressBar(delay);
|
||||
// Save the location first.
|
||||
this.previousLocation = this.props.location;
|
||||
this.previousLocation = normalizeLocation(this.props.location);
|
||||
this.setState({
|
||||
nextRouteHasLoaded: false,
|
||||
});
|
||||
|
||||
// Load data while the old screen remains.
|
||||
preload(routes, nextProps.location.pathname)
|
||||
preload(routes, nextLocation.pathname)
|
||||
.then(() => {
|
||||
clientLifecyclesDispatcher.onRouteUpdate({
|
||||
previousLocation: this.previousLocation,
|
||||
location: nextProps.location,
|
||||
location: nextLocation,
|
||||
});
|
||||
// Route has loaded, we can reset previousLocation.
|
||||
this.previousLocation = null;
|
||||
|
@ -59,7 +61,7 @@ class PendingNavigation extends React.Component {
|
|||
},
|
||||
this.stopProgressBar,
|
||||
);
|
||||
const {hash} = nextProps.location;
|
||||
const {hash} = nextLocation;
|
||||
if (!hash) {
|
||||
window.scrollTo(0, 0);
|
||||
} else {
|
||||
|
@ -94,7 +96,7 @@ class PendingNavigation extends React.Component {
|
|||
this.clearProgressBarTimeout();
|
||||
this.progressBarTimeout = setTimeout(() => {
|
||||
clientLifecyclesDispatcher.onRouteUpdateDelayed({
|
||||
location: this.props.location,
|
||||
location: normalizeLocation(this.props.location),
|
||||
});
|
||||
nprogress.start();
|
||||
}, delay);
|
||||
|
@ -107,7 +109,9 @@ class PendingNavigation extends React.Component {
|
|||
|
||||
render() {
|
||||
const {children, location} = this.props;
|
||||
return <Route location={location} render={() => children} />;
|
||||
return (
|
||||
<Route location={normalizeLocation(location)} render={() => children} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import normalizeLocation from '../normalizeLocation';
|
||||
|
||||
describe('normalizeLocation', () => {
|
||||
test('rewrite locations with index.html', () => {
|
||||
expect(
|
||||
normalizeLocation({
|
||||
pathname: '/docs/introduction/index.html',
|
||||
search: '?search=foo',
|
||||
hash: '#features',
|
||||
}),
|
||||
).toEqual({
|
||||
pathname: '/docs/introduction',
|
||||
search: '?search=foo',
|
||||
hash: '#features',
|
||||
});
|
||||
|
||||
expect(
|
||||
normalizeLocation({
|
||||
pathname: '/index.html',
|
||||
search: '',
|
||||
hash: '#features',
|
||||
}),
|
||||
).toEqual({
|
||||
pathname: '/',
|
||||
search: '',
|
||||
hash: '#features',
|
||||
});
|
||||
});
|
||||
|
||||
test('untouched pathnames', () => {
|
||||
expect(
|
||||
normalizeLocation({
|
||||
pathname: '/docs/introduction',
|
||||
search: '',
|
||||
hash: '#features',
|
||||
}),
|
||||
).toEqual({
|
||||
pathname: '/docs/introduction',
|
||||
search: '',
|
||||
hash: '#features',
|
||||
});
|
||||
|
||||
expect(
|
||||
normalizeLocation({
|
||||
pathname: '/docs/introduction/foo.html',
|
||||
search: '',
|
||||
hash: '#bar',
|
||||
}),
|
||||
).toEqual({
|
||||
pathname: '/docs/introduction/foo.html',
|
||||
search: '',
|
||||
hash: '#bar',
|
||||
});
|
||||
|
||||
expect(
|
||||
normalizeLocation({
|
||||
pathname: '/',
|
||||
}),
|
||||
).toEqual({
|
||||
pathname: '/',
|
||||
});
|
||||
});
|
||||
});
|
34
packages/docusaurus/src/client/normalizeLocation.js
Normal file
34
packages/docusaurus/src/client/normalizeLocation.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// Memoize previously normalized pathnames.
|
||||
const pathnames = {};
|
||||
|
||||
function normalizeLocation(location) {
|
||||
if (pathnames[location.pathname]) {
|
||||
return {
|
||||
...location,
|
||||
pathname: pathnames[location.pathname],
|
||||
};
|
||||
}
|
||||
|
||||
let pathname = location.pathname || '/';
|
||||
pathname = pathname.trim().replace(/\/index\.html$/, '');
|
||||
|
||||
if (pathname === '') {
|
||||
pathname = '/';
|
||||
}
|
||||
|
||||
pathnames[location.pathname] = pathname;
|
||||
|
||||
return {
|
||||
...location,
|
||||
pathname,
|
||||
};
|
||||
}
|
||||
|
||||
export default normalizeLocation;
|
Loading…
Add table
Reference in a new issue