Router
TIP
The routing usage described below can be found in umi-examples/routes and find the sample code in umi-examples/routes-via-config.
Umi automatically generates routing configurations based on the pages
directory.
Conventional Routing
Basic Routing
Assume that the pages
directory structure is as follows:
+ pages/
+ users/
- index.js
- list.js
- index.js
Then, umi will automatically generate the routing configuration as follows:
[
{ path: '/', component: './pages/index.js' },
{ path: '/users/', component: './pages/users/index.js' },
{ path: '/users/list', component: './pages/users/list.js' },
]
Dynamic Routing
As agreed in umi, directories or files with the $
prefix are dynamic routes.
For example, the following directory structure:
+ pages/
+ $post/
- index.js
- comments.js
+ users/
$id.js
- index.js
The routing configuration will be generated as follows:
[
{ path: '/', component: './pages/index.js' },
{ path: '/users/:id', component: './pages/users/$id.js' },
{ path: '/:post/', component: './pages/$post/index.js' },
{ path: '/:post/comments', component: './pages/$post/comments.js' },
]
Optional Dynamic Routing
In umi, dynamic routing is an optional dynamic route if it has a $
suffix.
For example, the following structure:
+ pages/
+ users/
- $id$.js
- index.js
The routing configuration will be generated as follows:
[
{ path: '/': component: './pages/index.js' },
{ path: '/users/:id?': component: './pages/users/$id$.js' },
]
Nested Routing
When there is _layout.js
in the umi directory, a nested route will be generated, with _layout.js
as the layout of the directory.
For example, the following directory structure:
+ pages/
+ users/
- _layout.js
- $id.js
- index.js
The routing configuration will be generated as follows:
[
{ path: '/users', component: './pages/users/_layout.js',
routes: [
{ path: '/users/', component: './pages/users/index.js' },
{ path: '/users/:id', component: './pages/users/$id.js' },
],
},
]
Global Layout
The convention src/layouts/index.js
is a global route, returning a React component, and rendering the child components via props.children
.
Example:
export default function(props) {
return (
<>
<Header />
{ props.children }
<Footer />
</>
);
}
Different Global Layout
You may need to output a different global layout for different routes. umi does not support such a configuration, but you can still distinguish between location.path and render different layouts in layouts/index.js
.
For example, if you want to output a simple layout for /login,
export default function(props) {
if (props.location.pathname === '/login') {
return <SimpleLayout>{ props.children }</SimpleLayout>
}
return (
<>
<Header />
{ props.children }
<Footer />
</>
);
}
404 Routing
The convention pages/404.js
is a 404 page and needs to return a React component.
Example:
export default () => {
return (
<div>I am a customized 404 page</div>
);
};
Note: In development mode, umi will add a default 404 page to aid development, but you can still verify the 404 page by precisely accessing
/404
.
Extending Routing by Annotation
The first comment of the contracted routing file is used to extend the route if it contains a configuration in the yaml format.
Example:
+ pages/
- index.js
If pages/index.js
contains:
/**
* title: Index Page
* Routes:
* - ./src/routes/a.js
* - ./src/routes/b.js
*/
A route configuration is generated:
[
{ path: '/', component: './index.js',
title: 'Index Page',
Routes: [ './src/routes/a.js', './src/routes/b.js' ],
},
]
Configuration Routing
If you prefer to use a configured route, you can configure routes
in the configuration file either .umirc.(ts|js)
or config/config.(ts|js)
, this configuration item will not be parsed for the src/pages
directory.
Example:
export default {
routes: [
{ path: '/', component: './a' },
{ path: '/list', component: './b', Routes: ['./routes/PrivateRoute.js'] },
{ path: '/users', component: './users/_layout',
routes: [
{ path: '/users/detail', component: './users/detail' },
{ path: '/users/:id', component: './users/id' }
]
},
],
};
note:
- component is relative to the
src/pages
directory
Permission Routing
The permission routing of umi is implemented by configuring the Routes
attribute of the route. The convention is added by the yaml annotation, and the configuration formula can be directly matched.
For example, the following configuration:
[
{ path: '/', component: './pages/index.js' },
{ path: '/list', component: './pages/list.js', Routes: ['./routes/PrivateRoute.js'] },
]
Then umi will render /list
with ./routes/PrivateRoute.js
.
Example of ./routes/PrivateRoute.js
file:
export default (props) => {
return (
<div>
<div>PrivateRoute (routes/PrivateRoute.js)</div>
{ props.children }
</div>
);
}
Route Transition Effects
There are several ways to implement route transition effects. Here is an example of react-transition-group.
Install dependencies first,
$ yarn add react-transition-group
In the layout component (layouts/index.js
or _layout.js
in the pages subdirectory), wrap a subassembly with TransitionGroup
and CSSTransition
and use location.pathname
as the key.
import withRouter from 'umi/withRouter';
import { TransitionGroup, CSSTransition } from "react-transition-group";
export default withRouter(
({ location }) =>
<TransitionGroup>
<CSSTransition key={location.pathname} classNames="fade" timeout={300}>
{ children }
</CSSTransition>
</TransitionGroup>
)
The fade
style used above can be defined in global.css
under src
:
.fade-enter {
opacity: 0;
z-index: 1;
}
.fade-enter.fade-enter-active {
opacity: 1;
transition: opacity 250ms ease-in;
}
Bread Crumbs
There are many ways to implement breadcrumbs. Here is an example of react-router-breadcrumbs-hoc.
Install dependencies first,
$ yarn add react-router-breadcrumbs-hoc
Then implement a Breakcrumbs.js
, such as:
import NavLink from 'umi/navlink';
import withBreadcrumbs from 'react-router-breadcrumbs-hoc';
// More configuration please go to https://github.com/icd2k3/react-router-breadcrumbs-hoc
const routes = [
{ path: '/', breadcrumb: 'home' },
{ path: '/list', breadcrumb: 'List Page' },
];
export default withBreadcrumbs(routes)(({ breadcrumbs }) => (
<div>
{breadcrumbs.map((breadcrumb, index) => (
<span key={breadcrumb.key}>
<NavLink to={breadcrumb.props.match.url}>
{breadcrumb}
</NavLink>
{(index < breadcrumbs.length - 1) && <i> / </i>}
</span>
))}
</div>
));
Then introduce this React component where you need it.
Enable Hash Routing
Umi defaults to the Browser History. If you want to use Hash History, you need to configure:
export default {
history: 'hash',
}
Scroll to Top
Decide whether to scroll to top in the componentDidUpdate
of the layout component (layouts/index.js
or the _layout.js
in the pages subdirectory), for example:
import { Component } from 'react';
import withRouter from 'umi/withRouter';
class Layout extends Component {
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
window.scrollTo(0, 0);
}
}
render() {
return this.props.children;
}
}
export default withRouter(Layout);