我知道之前已经问过这个问题,但我一直有这个问题。
我遇到的问题是,当我使用页面布局类似的组件来包装我的路线时,更改路径时此页面布局重新渲染。
在react-router v3中,我做了类似的事情:
<Router history={this.props.history}>
<Route path="/">
<IndexRedirect to="/Dossiers" />
<Route path="/Dossiers" component={MainLayout}>
<IndexRoute component={DossiersPage} />
<Route path="/Dossiers/:dossierId/:title" component={DossierDetailsPage} />
</Route>
</Route>
</Router>
当移动路径时,这不会重新呈现MainLayout
组件(可以通过在MainLayout
内放置一些状态来轻松检查。)
现在,在react-router v4 中,我尝试了几种方法:
Switch
组件MainLayout
RouteWithMainLayout
的{{1}}组件(如此处所述:https://simonsmith.io/reusing-layouts-in-react-router-4/)但是,我尝试过的所有解决方案似乎都会重新呈现Route
组件,基本上会导致MainLayout
重置为其初始值。
tldr; 如何在state
中创建包装组件,在更改路径时不会重新呈现
答案 0 :(得分:2)
我整理了一个代码框示例,说明了我如何使用“页面布局”类型的组件。它使用React Router v4.1.2。
https://codesandbox.io/s/Vmpy1RzE1
正如您在问题中描述的那样,正如Matt的回答所述,MainLayout
组件包裹了路径。
<BrowserRouter>
<MainLayout>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
</Switch>
</MainLayout>
</BrowserRouter>
在导航应用程序时,MainLayout
组件确实重新呈现,因为React调用了render
。但是,MainLayout
组件永远不会卸载,因此状态永远不会重新初始化。
我在示例中放置了一些console.log
来展示这一点。我的MainLayout
看起来像这样:
export default class MainLayout extends React.Component {
state = {
layoutCreatedOn: Date(),
};
componentDidMount() {
//This will not fire when we navigate the app.
console.log('layout did mount.');
}
componentWillUnmount() {
//This won't fire,
// because our "shared page layout" doesn't unmount.
console.log('layout will unmount');
}
render() {
//This does fire every time we navigate the app.
// But it does not re-initialize the state.
console.log('layout was rendered');
return (
<div styles={styles}>
<h5>
Layout created: {this.state.layoutCreatedOn}
</h5>
<Sidebar />
{this.props.children}
</div>
);
}
}
当您点击应用时,您会看到一些内容。
componentDidMount
只发射一次。 componentWillUnmount
永远不会开火。 render
都会触发。 layoutCreatedOn
属性显示了我浏览应用的同一时间。页面加载时初始化状态,并且从不重新初始化。答案 1 :(得分:0)
您不再需要MainLayout
,而只需将所有路线包裹在<Router history={this.props.history}>
<Switch>
<MainLayout>
<Route path="/" component={DossiersPage}/>
<Route path="/Dossiers/:dossierId/:title" component={DossierDetailsPage} />
</MainLayout>
</Switch>
</Router>
组件中,例如:
for beg in pd.date_range('2013-12-21', '2017-05-17', freq='90D'):
smpl = merged.loc[beg:beg + pd.Timedelta('20D')]
...
答案 2 :(得分:0)
这是here所述的React Router v4的正确解决方案
因此,基本上,您需要使用render方法来渲染布局并像这样包装您的组件:
<Router>
<Switch>
<Route path={ROUTES.LOGIN} render={props =>
<LoginLayout {...props}>
<Login {...props} />
</LoginLayout>
} />
<Route path={ROUTES.REGISTER} render={props =>
<LoginLayout {...props}>
<Register {...props} />
</LoginLayout>
} />
<Route path="*" component={NotFound} />
</Switch>
</Router>
更改路线时,这不会导致布局的重新渲染。
当您有许多具有不同布局的不同组件时,可以继续进行操作,并在路由配置数组中进行定义,例如issue I linked中的示例:
const routes = [
{ path: '/',
exact: true,
component: Home
},
{ path: '/about',
component: About,
},
{ path: '/cart',
component: Three,
}
]
<Router>
<Switch>
{routes.map({ path, exact, component: Comp } => (
<Route path={path} exact={exact} render={(props) => (
<LayoutWithSidebarAndHeader {...props}>
<Comp {...props}/>
</LayoutWithSidebarAndHeader>
)}/>
))}
<Route component={Error404}/>
</Switch>
</Router>