react-router v4:判断路由是否已经从组件外部匹配
react-router v4: Determine if route has been matched from outside the component
我有一个组件 总是 需要渲染,但只有在没有匹配的路由时才应该可见 (<Iframe isVisible={ifNoRoutesMatched} />
)。
到目前为止,我还没有找到一个很好的方法来检查是否是这种情况。我走下了这条可怕的路线,将变量设置为组件包装器状态,但必须有更好的方法!?这也需要 withRouter
和 PureComponent
否则 catchAllWrapper
会导致无限渲染循环:
class App extends PureComponent {
state = {
routeMatched: false,
}
catchAllWrapper = () => {
this.setState({ routeMatched: false });
return null;
}
routeWrapper = (RouteComponent) => {
const RouteWrapper = (props) => {
this.setState({ routeMatched: true });
return <RouteComponent {...props} />;
};
return RouteWrapper;
}
render() {
return (
<div className="App">
<Navigation />
<Switch>
<Route path="/chat" component={this.routeWrapper(Chat)} />
...more routes...
<Route component={this.catchAllWrapper} />
</Switch>
<Iframe isVisible={!this.state.routeMatched} />
</div>
);
}
}
export default withRouter(App);
我宁愿手动比较路由字符串数组,也不愿增加这种复杂性!
this.props.match
只有在匹配组件内部匹配的路由信息,所以它没什么用。
有更好的方法吗?
用例:它是一个 iframe,在某些路由上加载了遗留应用程序,因此不应在路由之间销毁和重新呈现它
要在没有路由匹配时显示组件,您可以使用以下代码:
<Switch>
{this.props.notLoggedIn === true
? <Route path='/' component={LandingPage}/>
: <Dashboard />
}
<Route component={PageNotFound}/>
</Switch>
在上述情况下,我将登录页面显示为默认路由,如果用户已登录,则会显示仪表板(包含更多路由,例如您的聊天路由)。
如果没有匹配的路由,则显示 PageNotFound
组件。
有关工作示例,请随时查看:https://github.com/osamamaruf/reactnd-project-would-you-rather/blob/master/src/components/App.js
回购 link 是:https://github.com/osamamaruf/reactnd-project-would-you-rather
为什么不为路由器创建一个轻量级虚拟组件以自由挂载和卸载,然后将当前 class 的回调方法绑定到其生命周期事件?
class Dummy extends Component {
componentDidMount() {
this.props.didMount();
}
componentWillUnmount() {
this.props.willUnmount();
}
render() {
return null;
}
}
class App extends Component {
state = {
showIframe: false,
}
cbDidMount = () => {
this.setState({ showIframe: true });
}
cbWillUnmount = () => {
this.setState({ showIframe: false });
}
render() {
return (
<div className="App">
<Navigation />
<Switch>
<Route path="/chat" component={Chat} />
{/* more routes */}
<Route render={() => <Dummy didMount={this.cbDidMount} willUnmount={this.cbWillUnmount} />} />
</Switch>
<Iframe isVisible={this.state.showIframe} />
</div>
);
}
}
这应该可以为您完成。在组件内部使用 Route that does not have a path
property (these always render) and you can check for a null match。
这是一个有效的CodeSandBox Example
打开底部的控制台可以看到一直在渲染
我有一个组件 总是 需要渲染,但只有在没有匹配的路由时才应该可见 (<Iframe isVisible={ifNoRoutesMatched} />
)。
到目前为止,我还没有找到一个很好的方法来检查是否是这种情况。我走下了这条可怕的路线,将变量设置为组件包装器状态,但必须有更好的方法!?这也需要 withRouter
和 PureComponent
否则 catchAllWrapper
会导致无限渲染循环:
class App extends PureComponent {
state = {
routeMatched: false,
}
catchAllWrapper = () => {
this.setState({ routeMatched: false });
return null;
}
routeWrapper = (RouteComponent) => {
const RouteWrapper = (props) => {
this.setState({ routeMatched: true });
return <RouteComponent {...props} />;
};
return RouteWrapper;
}
render() {
return (
<div className="App">
<Navigation />
<Switch>
<Route path="/chat" component={this.routeWrapper(Chat)} />
...more routes...
<Route component={this.catchAllWrapper} />
</Switch>
<Iframe isVisible={!this.state.routeMatched} />
</div>
);
}
}
export default withRouter(App);
我宁愿手动比较路由字符串数组,也不愿增加这种复杂性!
this.props.match
只有在匹配组件内部匹配的路由信息,所以它没什么用。
有更好的方法吗?
用例:它是一个 iframe,在某些路由上加载了遗留应用程序,因此不应在路由之间销毁和重新呈现它
要在没有路由匹配时显示组件,您可以使用以下代码:
<Switch>
{this.props.notLoggedIn === true
? <Route path='/' component={LandingPage}/>
: <Dashboard />
}
<Route component={PageNotFound}/>
</Switch>
在上述情况下,我将登录页面显示为默认路由,如果用户已登录,则会显示仪表板(包含更多路由,例如您的聊天路由)。
如果没有匹配的路由,则显示 PageNotFound
组件。
有关工作示例,请随时查看:https://github.com/osamamaruf/reactnd-project-would-you-rather/blob/master/src/components/App.js
回购 link 是:https://github.com/osamamaruf/reactnd-project-would-you-rather
为什么不为路由器创建一个轻量级虚拟组件以自由挂载和卸载,然后将当前 class 的回调方法绑定到其生命周期事件?
class Dummy extends Component {
componentDidMount() {
this.props.didMount();
}
componentWillUnmount() {
this.props.willUnmount();
}
render() {
return null;
}
}
class App extends Component {
state = {
showIframe: false,
}
cbDidMount = () => {
this.setState({ showIframe: true });
}
cbWillUnmount = () => {
this.setState({ showIframe: false });
}
render() {
return (
<div className="App">
<Navigation />
<Switch>
<Route path="/chat" component={Chat} />
{/* more routes */}
<Route render={() => <Dummy didMount={this.cbDidMount} willUnmount={this.cbWillUnmount} />} />
</Switch>
<Iframe isVisible={this.state.showIframe} />
</div>
);
}
}
这应该可以为您完成。在组件内部使用 Route that does not have a path
property (these always render) and you can check for a null match。
这是一个有效的CodeSandBox Example
打开底部的控制台可以看到一直在渲染