【问题标题】:In React, why route can work properly without path在 React 中,为什么 route 可以在没有路径的情况下正常工作
【发布时间】:2022-01-03 16:08:12
【问题描述】:

代码如下。 {...rest} 不包含path,路由不应该正确路由,但实际上它可以路由到路径(/movies/:id)。为什么会这样?

<ProtectedRoute path="/movies/:id" component={MovieForm} />
 
const ProtectedRoute = ({ path, component: Component, render, ...rest }) => {
  console.log("rest: ", { ...rest });
  return (
    <Route
      //   path={path}
      {...rest}
      render={(props) => {
        console.log(props);
        if (!auth.getCutterntUser()) return <Redirect to="/login" />;
        return Component ? <Component {...props} /> : render(props);
      }}
    />
  );

【问题讨论】:

    标签: reactjs react-router


    【解决方案1】:

    路由仍然有效的原因是您在 PrivateRoute 组件上指定了一个 path 属性,这是 Switch 用于路径匹配的组件。

    v5 评测Switchsource code

    /**
     * The public API for rendering the first <Route> that matches.
     */
    class Switch extends React.Component {
      render() {
        return (
          <RouterContext.Consumer>
            {context => {
              invariant(context, "You should not use <Switch> outside a <Router>");
    
              const location = this.props.location || context.location;
    
              let element, match;
    
              // We use React.Children.forEach instead of React.Children.toArray().find()
              // here because toArray adds keys to all child elements and we do not want
              // to trigger an unmount/remount for two <Route>s that render the same
              // component at different URLs.
              React.Children.forEach(this.props.children, child => {
                if (match == null && React.isValidElement(child)) {
                  element = child;
    
                  const path = child.props.path || child.props.from;
    
                  match = path
                    ? matchPath(location.pathname, { ...child.props, path })
                    : context.match;
                }
              });
    
              return match
                ? React.cloneElement(element, { location, computedMatch: match })
                : null;
            }}
          </RouterContext.Consumer>
        );
      }
    }
    

    Switch 遍历其子元素并检查 pathfrom 道具路径值,并计算匹配。对于计算出的匹配,它会克隆并返回匹配的element

    <ProtectedRoute
      path="/movies/:id" // <-- child component path specified here
      component={MovieForm}
    />
    

    事实上,即使像 divpath 属性这样简单的东西也可以工作,例如:

    <div path="/movies/:id">TEST</div>
    

    这仅解释了Switch 内的匹配,但现在您想知道为什么PrivateRoute 渲染的Route 组件仍然有效。这是因为任何不是由Switch 直接渲染的Route 现在都被包含性地匹配和渲染(就好像它只在一个Router 组件中)。 Route 没有路径,因此它匹配 anything 并被渲染。

    现在应该很明显Route 组件本身是无关紧要的。您可以稍微简化一下PrivateRoute;有条件地渲染一个 Route 与所有通过的路由道具,或 Redirect 到登录页面。

    const ProtectedRoute = (props) => {
      return auth.getCutterntUser()
        ? <Route {...props} />
        : <Redirect to="/login" />;
    };
    

    【讨论】:

      猜你喜欢
      • 2017-09-23
      • 2020-03-07
      • 2011-04-19
      • 1970-01-01
      • 2016-11-27
      • 2019-02-07
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      相关资源
      最近更新 更多