react-router v4:当子路由未命中时如何避免呈现父路由 [英] react-router v4: how to avoid rendering parent routes when child routes miss

查看:93
本文介绍了react-router v4:当子路由未命中时如何避免呈现父路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将我的大多数路线呈现为AppShell组件的子项,该组件包含一个导航栏.但是我想将我的404路由呈现为不包装在AppShell中的独立组件.

I'm trying to render most of my routes as children of an AppShell component, which contains a navbar. But I want to render my 404 route as a standalone component not wrapped in AppShell.

<Router>
  <Route component={AppShell}>
    <Route path="/about" component={About} />
    <Route path="/" component={Home} />
  </Route>
  <Route path="*" component={NotFound} />
</Router>

一切都按要求进行:

  • /呈现<AppShell><Home /></AppShell>
  • /about呈现<AppShell><About /></AppShell>
  • /blah呈现<NotFound />
  • / renders <AppShell><Home /></AppShell>
  • /about renders <AppShell><About /></AppShell>
  • /blah renders <NotFound />

现在我正在执行此操作,但问题是它呈现了AppShell(没有子项,但仍然有导航栏):

Right now I'm doing this, but the problem is it renders AppShell (with no children, but still a navbar):

const Routes = () => (
  <div>
    <AppShell>
      <Match exactly pattern="/" component={Home} />
      <Match pattern="/about" component={About} />
    </AppShell>
    <Miss component={NotFound} />
  </div>
)

与此:

  • /呈现<div><AppShell><Home /></AppShell></div>(良好)
  • /about呈现<div><AppShell><About /></AppShell></div>(良好)
  • /blah渲染<div><AppShell /><NotFound /></div> (问题-我想摆脱<AppShell />)
  • / renders <div><AppShell><Home /></AppShell></div> (good)
  • /about renders <div><AppShell><About /></AppShell></div> (good)
  • /blah renders <div><AppShell /><NotFound /></div> (problem -- I want to get rid of the <AppShell />)
const InAppShell = (): React.Element<any> => (
  <AppShell>
    <Match pattern="/about" component={About} />
    <Match pattern="/contact" component={Contact} />
  </AppShell>
)

const App = (): React.Element<any> => (
  <div>
    <Match pattern={['/contact', '/about']} component={InAppShell} />
    <Miss component={NotFound} />
  </div>
)

并且将数组patternexactly一起使用可用于根路由:

但是然后我必须将所有可能的子路线放在pattern数组中...

And using an array pattern with exactly works with the root route:

But then I have to put all possible child routes in the pattern array...

const InAppShell = (): React.Element<any> => (
  <AppShell>
    <Match exactly pattern="/" component={Home} />
    <Match pattern="/about" component={About} />
  </AppShell>
)

const App = (): React.Element<any> => (
  <div>
    <Match exactly pattern={["/", "/about"]} component={InAppShell} />
    <Miss component={NotFound} />
  </div>
)

但是在具有大量路由的大型应用程序中,这将是非常不必要的.

But that would be pretty unwieldly in a large app with a bunch of routes.

const InAppShell = (): React.Element<any> => (
  <AppShell>
    <Match exactly pattern="/" component={Home} />
    <Match pattern="/about" component={About} />
    <Match pattern="/contact" component={Contact} />
  </AppShell>
)

const App = (): React.Element<any> => (
  <div>
    <Match exactly pattern="/" component={InAppShell} />
    <Match pattern={["/about", "/contact"]} component={InAppShell} />
    <Miss component={NotFound} />
  </div>
)

但是,每次我往返于本国路线时,都会重新安装<AppShell>.

But this would remount <AppShell> every time I transition to and from the home route.

这里似乎没有理想的解决方案;我认为这是v4需要解决的一个基本的API设计挑战.

There doesn't seem to be an ideal solution here; I think this is a fundamental API design challenge v4 will need to solve.

如果我能做类似<Match exactlyPattern="/" pattern={["/about", "/contact"]} component={InAppShell} /> ...

If only I could do something like <Match exactlyPattern="/" pattern={["/about", "/contact"]} component={InAppShell} />...

推荐答案

我一直在解决同一个问题-我认为您可能想要这样的东西,即全局404":

I've been working around the same issue - I think you may want something like this, a 'global 404':

https://codepen.io/pshrmn/pen/KWeVrQ

const {
  HashRouter,
  Route,
  Switch,
  Link,
  Redirect
} = ReactRouterDOM

const Global404 = () => (
  <div>
    <h1>Oh, no!</h1>
    <p>You weren't supposed to see this... it was meant to be a surprise!</p>
  </div>
)

const Home = () => (
  <div>
    The links to "How?" and "Random" have no matching routes, so if you click on either of them, you will get a "global" 404 page.
  </div>
)
const Question = ({ q }) => (
  <div>
    <div>Question: {q}</div>
    <div>Answer: I have no idea</div>
  </div>
)
const Who = () => <Question q={"Who?"}/>
const What = () => <Question q={"What?"}/>
const Where = () => <Question q={"Where?"}/>
const When = () => <Question q={"When?"}/>
const Why = () => <Question q={"Why?"}/>

const RedirectAs404 = ({ location }) => 
  <Redirect to={Object.assign({}, location, { state: { is404: true }})}/>

const Nav = () => (
  <nav>
    <ul>
      <li><Link to='/'>Home</Link></li>
      <li><Link to='/faq/who'>Who?</Link></li>
      <li><Link to='/faq/what'>What?</Link></li>
      <li><Link to='/faq/where'>Where?</Link></li>
      <li><Link to='/faq/when'>When?</Link></li>
      <li><Link to='/faq/why'>Why?</Link></li>
      <li><Link to='/faq/how'>How?</Link></li>
      <li><Link to='/random'>Random</Link></li>
    </ul>
  </nav>
)

const App = () => (
  <Switch>
    <Route exact path='/' component={Home}/>
    <Route path='/faq' component={FAQ}/>
    <Route component={RedirectAs404}/>
  </Switch>
)

const FAQ = () => (
  <div>
    <h1>Frequently Asked Questions</h1>
    <Switch>
      <Route path='/faq/who' component={Who}/>
      <Route path='/faq/what' component={What}/>
      <Route path='/faq/where' component={Where}/>
      <Route path='/faq/when' component={When}/>
      <Route path='/faq/why' component={Why}/>
      <Route component={RedirectAs404}/>
    </Switch>
  </div>
)

ReactDOM.render((
  <HashRouter>
    <div>
      <Nav />
      <Route render={({ location }) => (
        location.state && location.state.is404
          ? <Global404 />
          : <App />
      )}/>
    </div>
  </HashRouter>
), document.getElementById('root'))

这篇关于react-router v4:当子路由未命中时如何避免呈现父路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆