React刷新当前路由
前言
- 之前在项目里写过点击当前地址由刷新路由,也没认真总结为什么会导致这样,以至于在新开始一个项目的时候会不明白为什么这样写会导致当前路由的更新。
使当前路由更新的文件main.tsx 和 Router.tsx 组件结构
把Switch 组件放在 main.tsx件,Route 独放在Router.tsx
** main.tsx **
import * as React from "react";
import {MemoryRouter,Switch} from "react-router-dom";
import SlideMenu from "@js/containers/SlideMenu";
import Head from "@js/containers/Head";
import MainRouter from "@js/Router";
import {createNotice} from "@js/common/toast/index";
import {createLoad} from "@js/common/icon/loadMethod";
type appProps = {
};
type appState = {
};
class App extends React.PureComponent<appProps, appState>{
upDom(){
createNotice();
createLoad();
}
componentDidMount(){
this.upDom();
}
render() {
return (
<MemoryRouter>
<SlideMenu />
<div className="g-content">
<div className="wrap-content">
<Head />
<div className="g-main">
<Switch>
<MainRouter />
</Switch>
<div id="wrap-modal"/>
<div id="wrap-loading"/>
<div id="wrap-notice"/>
</div>
</div>
</div>
</MemoryRouter>
);
}
}
export default App;
Router.tsx
import { Route } from "react-router-dom";
import * as React from "react";
import {Loading} from "@js/common/icon/index";
import * as loadable from "react-loadable";
import DefaultCom from "@js/containers/default";
import noticeFn from "@js/common/toast/index";
class Main extends React.PureComponent{
componentWillUpdate(){
noticeFn.clear();
}
render(){
const report = loadable({
loader: () => import( /*webpackChunkName: "report" */"./containers/report/index"),
loading: () => <Loading.LoadingCom />
});
const myReport = loadable({
loader: () => import( /*webpackChunkName: "myReport" */"./containers/list-report/index"),
loading: () => <Loading.LoadingCom />
});
const analysis = loadable({
loader: () => import( /*webpackChunkName: "analysisBasic" */"./containers/analysis/index"),
loading: () => <Loading.LoadingCom />
});
const newAnalysis = loadable({
loader: () => import( /*webpackChunkName: "newAnalysis" */"./containers/newAnalysis/Analysis"),
loading: () => <Loading.LoadingCom />
});
return (
<>
<Route path="/report" component={report} />
<Route path="/my_report" component={myReport} />
<Route path="/my_back" component={myReport} />
<Route path="/all_allot_yet" component={myReport} />
<Route path="/all_event" component={myReport} />
<Route path="/statistics_base" component={analysis} />
<Route path="/my_analyze" component={analysis} />
<Route path="/analyzes" component={newAnalysis} />
<Route path="/report_analyze" component={newAnalysis} />
<Route path="/res_analyze" component={newAnalysis} />
<Route path="/" exact={true} component={DefaultCom} />
</>
);
}
}
export default MainRouter;
Switch 与 Route 组件在不同组件 App 和 mainRouter 里
- Switch匹配路由地址,传递给子组件
- Router 收到路由地址,渲染对应的路由组件
- 当Switch 和 Router 在不同的组件App 和 mainRouter 的时候,当匹配路由地址时,不管是相同还是不相同的地址,如点击菜单,会引起mainRouter更新,调用 其render函数。
- 关键的地方来了:
-
- 把按需加载的组件如 report 写在render里
-
- 每次render 时,重新生成新的组件report,这个不影响按需加载,已经加载的js 不会再加载,只是使组件重新渲染
-
- 要是不把按需加载这一部分写在render 里,写在别的地方如组件类的外面,即使每次render ,按需加载的组件都是同一个,不会引起路由组件report的重新渲染
-
- 在线 demo (demo 内容与文章里代码不完全相同)
// Router.tsx
...
render(){
const report = loadable({
loader: () => import( /*webpackChunkName: "report" */"./containers/report/index"),
loading: () => <Loading.LoadingCom />
});
const myReport = loadable({
loader: () => import( /*webpackChunkName: "myReport" */"./containers/list-report/index"),
loading: () => <Loading.LoadingCom />
});
const analysis = loadable({
loader: () => import( /*webpackChunkName: "analysisBasic" */"./containers/analysis/index"),
loading: () => <Loading.LoadingCom />
});
const newAnalysis = loadable({
loader: () => import( /*webpackChunkName: "newAnalysis" */"./containers/newAnalysis/Analysis"),
loading: () => <Loading.LoadingCom />
});
return (
<>
...
<Route path="/my_report" component={myReport} />
<Route path="/my_back" component={myReport} />
<Route path="/all_allot_yet" component={myReport} />
<Route path="/all_event" component={myReport} />
<Route path="/statistics_base" component={analysis} />
...
</>
);
}
...
Switch 与 Route 组件在同一组件App里
- Switch 还是匹配路由地址,传递给子组件 Router
- Router 收到路由地址,渲染对应的路由组件
- Switch 匹配路由地址时,不管是相同还是不相同的地址,如点击菜单,不会引起App更新,所以不会调用 其render函数。
- 关键的地方来了:
-
- 即使把按需加载的组件如 report 写在render里
-
- 由于路由触发时,App 不会调用 render ,所以不会重新生成新的组件report
-
- report不会重新渲染
-
- 在线 demo (demo 内容与文章里代码不完全相同)
import * as React from "react";
import {MemoryRouter,Switch,Route} from "react-router-dom";
import SlideMenu from "@js/containers/SlideMenu";
import Head from "@js/containers/Head";
import MainRouter from "@js/Router";
import {createNotice} from "@js/common/toast/index";
import {createLoad} from "@js/common/icon/loadMethod";
import {Loading} from "@js/common/icon/index";
import * as loadable from "react-loadable";
import DefaultCom from "@js/containers/default";
import noticeFn from "@js/common/toast/index";
type appProps = {
};
type appState = {
};
class App extends React.PureComponent<appProps, appState>{
upDom(){
createNotice();
createLoad();
}
componentDidMount(){
this.upDom();
}
render() {
const report = loadable({
loader: () => import( /*webpackChunkName: "report" */"./containers/report/index"),
loading: () => <Loading.LoadingCom />
});
const myReport = loadable({
loader: () => import( /*webpackChunkName: "myReport" */"./containers/list-report/index"),
loading: () => <Loading.LoadingCom />
});
const analysis = loadable({
loader: () => import( /*webpackChunkName: "analysisBasic" */"./containers/analysis/index"),
loading: () => <Loading.LoadingCom />
});
const newAnalysis = loadable({
loader: () => import( /*webpackChunkName: "newAnalysis" */"./containers/newAnalysis/Analysis"),
loading: () => <Loading.LoadingCom />
});
return (
<MemoryRouter>
<SlideMenu />
<div className="g-content">
<div className="wrap-content">
<Head />
<div className="g-main">
<Switch>
<Route path="/report" component={report} />
<Route path="/my_report" component={myReport} />
<Route path="/my_back" component={myReport} />
<Route path="/all_allot_yet" component={myReport} />
<Route path="/all_event" component={myReport} />
<Route path="/statistics_base" component={analysis} />
<Route path="/my_analyze" component={analysis} />
<Route path="/analyzes" component={newAnalysis} />
<Route path="/report_analyze" component={newAnalysis} />
<Route path="/res_analyze" component={newAnalysis} />
<Route path="/" exact={true} component={DefaultCom} />
</Switch>
<div id="wrap-modal"/>
<div id="wrap-loading"/>
<div id="wrap-notice"/>
</div>
</div>
</div>
</MemoryRouter>
);
}
}
export default App;