2017-04-14 58 views
1

我试图迁移到使用React Router 4并且在理解<Switch>组件的逻辑时遇到了一些麻烦,因为它在docs中用于处理404(或不匹配的)路线。<Switch>组件在react-router-4中匹配null值

对于我的条目JavaScript文件,我设置了以下路线。

index.js

<Switch> 
    <Route path="/login" component={Login} /> 
    <Route path="/forgot-password" component={ForgotPassword} /> 
    <Route path="/email-verification" component={EmailVerification} /> 
    <Route component={App} /> 
</Switch> 

Login组件将检查以查看是否用户被验证,并且如果是这样,将用户重定向到该/dashboard路径(经由history.replace)。

App组件仅在用户通过身份验证时才可访问,并且它具有类似的检查以将用户重定向到/login(如果不是)。

在我App组件我有更多的规定航线上,我可以肯定的是只访问,如果用户登录。

App.js

<Switch> 
    <Route path="/dashboard" component={Dashboard} /> 
    <Route path="/accounts" component={Account} /> 
    <Authorize permissions={['view-admin']}> 
     <Route path="/admin" component={Admin} /> 
    </Authorize> 
    <Route path="/users" component={Users} /> 
    <Route component={NotFound} /> 
</Switch> 

就在这里我的问题 。对通过权限的Authorize组件会检查用户是否有这些权限,如果是这样,它使孩子们直接,如果不是,则返回从render()null

此处的预期行为是,<Route path="/admin" />在没有足够权限且<Route component={NotFound} />组件呈现时根本不呈现。

按照docs

呈现一个相匹配的第一个孩子。 A 没有路径总是匹配。

但是,如果我去任何航线宣告<Authorize>组件后,路由器匹配null。这意味着,根据上面的例子,去/users返回null。预期行为是否会返回<Switch/>组件中的第一个匹配项,即使它的值为null

我该如何为这种情况提供一个“全部通过”路由(404),而不需要为App.js中的许多经过身份验证的路由创建一个<PrivateRoute>组件?一个null值应该真的产生一个匹配?

+0

我有同样的问题。你有没有找到这方面的解决方案? – Salim

+0

我相信这个问题是由于我的组件造成的,但我从未发现这是为什么会出现这种情况。 – Himmel

回答

1

不幸的是,react-router的Switch组件不能与嵌套在其他组件中的路由一起工作,就像你的例子。如果检查the docs for Switch,它说:

一个<开关>的所有的孩子都应该是<路线>或<重定向>元素。

...因此,您的Authorize组件实际上并不是合法的,因为它是Switch的直接子项。

如果你有过the source code of the Switch component读,你会看到它,而邪恶地读取它的每一个孩子的道具和手动对每个孩子的path(或from)道具适用反应路由器的matchPath方法,以确定哪些人应被渲染。

因此,你的情况发生了什么是Switch迭代通过它的孩子,直到它到达你的Authorize组件。然后它查看该组件的道具,找不到pathfrom道具,并在未定义的路径上调用matchPath。当你注意到自己,“<路径>没有路径总是匹配”,所以matchPath返回true,并且开关呈现您的Authorize组件(忽略任何后续的路由或重定向,因为它认为它找到了匹配)。但是,Authorize组件中嵌套的“/ admin”路由与当前路径不匹配,因此您会从渲染中返回空结果。

我在工作中遇到类似的情况。我计划解决这个问题的方法是在我的路由代码中用一个自定义组件替换react路由器的Switch,该自定义组件会遍历其子代,然后依次手动渲染每个代码,并返回第一个返回非空值的结果。当我给它一个镜头时,我会更新这个答案。

编辑:那么,没有工作。我无法制定出一种支持的方式来手动调用子项上的“渲染”。对不起,我无法给你解决Switch的限制。