No longer advocate centralized routing! Nested routing is no longer the use of {props.children}. Each route is a React component.
react-router-dom
In the web side, you only need to import this package, because it takes a lot of things from the react router.
// @types/react-router-dom/index.d.ts export { ...... } from 'react-router';
Then look at the common functions
HashRouter / BrowerRouter
It is understood as a routing container. The sub components wrapped in it can use their own defined routing components.
// index.tsx import React from 'react'; import ReactDOM from 'react-dom'; import { HashRouter } from 'react-router-dom'; import App from './App'; ReactDOM.render( <HashRouter> <App /> </HashRouter> , document.getElementById('root') );
Route
Route component. When the route is matched, this location is rendered into the corresponding content.
- Path needs matching path
- component matches successfully rendered components
- exact match or not
<Route path="/home" exact component={ Home } />
In this case, it will only match if the path is / home. If there is no exact attribute, then when the path is / home, both the / and / home routing components will be rendered.
Nested Route
v4 and above no longer support the way of {props.children} for nested routing, but directly put the child routing component in the position that needs to be rendered in the parent component.
// App.tsx <div> <Route path="/" component={ Dashboard } /> </div> // Dashboard.tsx <div> <Header /> <Route path="/home" component={ Home } /> <Route path="/other" component={ Other } /> </div>
This nested routing method needs to ensure that the parent component has the same routing prefix (/) as the child component, and that the parent component does not have the exact attribute. (the purpose is to render the parent component first, and then match the child routing components defined inside the parent component)
Dynamic routing
Like other routing plug-ins, use colons to configure dynamic routes.
// Dashboard.tsx <div> <Header /> <Route path="/home" component={ Home } /> <Route path="/other" exact component={ Other } /> <Route path="/other/:id" component={ OtherDetail } /> </div>
/other/1
Will match/other
and/other/:id
These two routing components, according to the actual situation/other
Routing component settingsexact
Attribute.useParams Get route parameters
// @types/react-router/index.d.ts export function useParams<Params extends { [K in keyof Params]?: string } = {}>(): { [p in keyof Params]: string };
The useParams() method returns an object, and directly taking the property TS will prompt that the property does not exist in the empty object. According to the specification of TS, an interface can be defined in the dynamic routing component to define the parameters of routing.
// OtherDetail.tsx import React from 'react'; import { useParams } from 'react-router-dom'; interface RouteParams { id: string } export default () => { const params = useParams<RouteParams>(); return ( <div> //Dynamic route: {params.id} </div> ) }
props get route parameters
The props data type of routing component is RouteComponentProps
// @types/react-router/index.d.ts export interface RouteComponentProps<Params extends { [K in keyof Params]?: string } = {}, C extends StaticContext = StaticContext, S = H.LocationState> { history: H.History; location: H.Location<S>; match: match<Params>; staticContext?: C; }
There are many match attributes
// @types/react-router/index.d.ts export interface match<Params extends { [K in keyof Params]?: string } = {}> { params: Params; isExact: boolean; path: string; url: string; }
In dynamic routing / other/1, the value of props.match.url is / other/1, and the value of props.match.path is / other/:id. Getting the properties in props.match.params still tells TS which properties are available.
import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; interface RouteParams { id: string } export default (props: RouteComponentProps<RouteParams>) => { return ( <div> //Dynamic routing: {props.match.params.id} </div> ) }
useRouteMatch get route matching information
As mentioned above, we can use props to get the information related to routing, including match, params, etc. we can use props.match to get the matching information of routing. You can also use the useRouteMatch method.
// @types/react-router/index.d.ts export function useRouteMatch<Params extends { [K in keyof Params]?: string } = {}>( path?: string | string[] | RouteProps, ): match<Params> | null;
Note that the return value of useRouteMatch() may be null and cannot be accessed simply in the form of match. *.
// Other.tsx import React from 'react'; import { useRouteMatch } from 'react-router'; export default () => { const match = useRouteMatch(); return ( <div>Routing path:{ match && match.url }</div> ) }
useLocation and useHistory are used similarly.
Switch
Switch matches only the first routing component in the subcomponent. As mentioned earlier, without setting the exact property, / home will match / and / home routing components at the same time. Using switch can make a single match, but it is also related to the placement order.
<Switch> <Route path="/home" component={ Home } /> <Route path="/" component={ Dashboard } /> </Switch>
Link
The component encapsulating the < a > label performs route jump.
<Link to="/home">to home</Link>
NavLink
Similar to the use of Link, the active class name will be added by default to the component whose current routing path matches the to property.
<NavLink to="/home">to home</NavLink> <NavLink exact to="/other">to other</NavLink> <NavLink to="/other/1">to other/1</NavLink>
When you click the to other/1 link, the to other link will also be added with the active class name, which is similar to the Router component, so for such navigation, you usually need to add the exact attribute.
Redirect
The to property is used for redirection, which is usually used in Switch as the processing of matching failure.
Programming route
The history object returned by useHistory() calls the push method.
Parameter passing
params
// Routing component <Route path="/home/:id" component={ Home }/> // Home.tsx interface RouteParams { id: string } export default () => { const params = useParams<RouteParams>(); return ( <div> { params.id } </div> ) } // Link jump <Link to="/home/1">to home</Link> // history jump import { useHistory } from 'react-router-dom'; export default () => { const history = useHistory(); const pushRouteParams = () => { history.push('/home/1') }; return ( <div> <Button onClick={ pushRouteParams }>to /home/1</Button> </div> ); };
state
// Routing component <Route path="/home" component={ Home }/> // Home.tsx import { useLocation } from 'react-router-dom'; export default () => { const location = useLocation(); return ( <div> { location.state && location.state.id } </div> ) } // Link jump <Link to={{ pathname: '/home', state: { id: 1 } }}>to home</Link> // history jump history.push({ pathname: '/home', state: { id: 1 } })
query
// @types/history export interface Location<S = LocationState> { pathname: Pathname; search: Search; state: S; hash: Hash; key?: LocationKey; }
The location object has no query attribute. It should not provide this method
push and replace
// Link <Link to="/home" /> <Link to="/home" replace/> // history history.push(...) history.replace(...)
Hook function
After v4, functions such as onEnter, onUpdate, and onLeave are no longer provided. Instead, the routing components correspond to life cycle methods such as componentDidMount, componentDidUpdate, and componentWillUnmount in React, respectively. This happens to be replaced with the new feature useEffect.
Use useEffect in the routing component to control the routing permission with history.replace()
const history = useHistory(); const state = true; useEffect(() => { if (!state) { history.replace('/'); } });
It is also written as a custom Hook, which is used in multiple routing components
function useUserRole(state: boolean) { const history = useHistory(); useEffect(() => { if (!state) { history.replace('/'); } }); } useUserRole(false);