【问题标题】:React Router Redirect does not render the componentReact Router Redirect 不渲染组件
【发布时间】:2021-06-05 07:01:34
【问题描述】:

这是我的 App.js:

function App() {
  return (
    <BrowserRouter>
      <AuthProvider>
        <Switch>
          <PrivateRoute path="/" component={MainPage} />
          <PrivateRoute path="/admin" component={MainPage} />
          <Container
            className="d-flex align-items-center justify-content-center"
            style={{ minHeight: "100vh" }}
          >
            <div className="w-100" style={{ maxWidth: "400px" }}>
              <Route path="/signup" component={Signup} />
              <Route path="/login" component={Login} /> //The component part
              <Route path="/forgot-password" component={ForgotPassword} />
            </div>
          </Container>
        </Switch>
      </AuthProvider>
    </BrowserRouter>
  );
}

来自 firebase 的 PriveRoute 组件的身份验证上下文:

export default function PrivateRoute({ component: Component, ...rest }) {
  const { currentUser } = useAuth();

  return (
    <Route
      render={(props) => {
        return currentUser ? <Admin {...props} /> : <Redirect to="/login" />; // it redirects when the user does not log in.
      }}
    ></Route>
  );

登录组件:

export default function Login() {
  const emailRef = useRef();
  const passwordRef = useRef();
  const { login, currentUser } = useAuth();
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);
  const history = useHistory();

  if (currentUser) {
    history.push("/admin/mainpage");
  }
  async function handleSubmit(e) {
    e.preventDefault();

    try {
      setError("");
      setLoading(true);
      await login(
        emailRef.current.value + "@myosmail.com",
        passwordRef.current.value
      );
      history.push("/admin/mainpage");
    } catch {
      setError("Failed to log in");
    }

    setLoading(false);
  }

  return (
    <>
      <Card>
        <Card.Body>
          <h2 className="text-center mb-4">Log In</h2>
          {error && <Alert variant="danger">{error}</Alert>}
          <Form onSubmit={handleSubmit}>
            <Form.Group id="email">
              <Form.Label>Username</Form.Label>
              <Form.Control ref={emailRef} required />
            </Form.Group>
            <Form.Group id="password">
              <Form.Label>Password</Form.Label>
              <Form.Control type="password" ref={passwordRef} required />
            </Form.Group>
            <Button disabled={loading} className="w-100" type="submit">
              Log In
            </Button>
          </Form>
          <div className="w-100 text-center mt-3">
            <Link to="/forgot-password">Forgot Password?</Link>
          </div>
        </Card.Body>
      </Card>
      <div className="w-100 text-center mt-2">
        Need an account? <Link to="/signup">Sign Up</Link>
      </div>
    </>
  );
}

如果用户没有登录,我想构建一个组件,它无法访问我网站的内容,所以我构建了上面的组件。但问题是,当我打开我的页面并且没有登录时,页面将我重定向到“/login”,但没有呈现登录组件,我不明白问题出在哪里。我调试了我的组件,我看到我的代码首先转到 PrivateRoute 组件,然后它重定向到“/ login”,但是当页面重定向到 Login 时没有呈现任何内容。当我从 App.js 中删除 PrivateRoutes 时,我的代码工作正常。

【问题讨论】:

    标签: javascript reactjs react-router react-router-dom


    【解决方案1】:

    问题

    我的猜测是您首先在 Switch 组件中放置了一个“/”路径:

    <PrivateRoute path="/" component={MainPage} />
    

    重定向到“/login”有效,但随后Switch 匹配“/”部分并尝试再次呈现此私有路由。

    你的私有路由也有问题,它没有传递所有收到的Route 道具。

    解决方案

    修复私有路由组件传递所有道具。

    export default function PrivateRoute({ component: Component, ...rest }) {
      const { currentUser } = useAuth();
    
      return (
        <Route
          {...rest}
          render={(props) => {
            return currentUser ? <Admin {...props} /> : <Redirect to="/login" />;
          }}
        />
      );
    }
    

    Switch 组件路径顺序和特定性问题内,您希望将更特定的路径排序不太特定的路径之前。 “/”是所有路径的路径前缀,因此您希望在其他路径之后使用它。嵌套路由也需要在 Switch 内呈现,因此只返回和呈现一个匹配项。

    <BrowserRouter>
      <AuthProvider>
        <Switch>
          <Container
            className="d-flex align-items-center justify-content-center"
            style={{ minHeight: "100vh" }}
          >
            <div className="w-100" style={{ maxWidth: "400px" }}>
              <Switch>
                <Route path="/signup" component={Signup} />
                <Route path="/login" component={Login} /> //The component part
                <Route path="/forgot-password" component={ForgotPassword} />
              </Switch>
            </div>
          </Container>
          <PrivateRoute path={["/admin", "/"]} component={MainPage} />
        </Switch>
      </AuthProvider>
    </BrowserRouter>
    

    更新

    我对你的私有路由有点困惑,你在 component 属性上指定了 MainPage 组件,然后在其中渲染了一个 Admin 组件。通常,一个更不可知的PrivateRoute 组件可能看起来更像:

    const PrivateRoute = props => {
      const { currentUser } = useAuth();
    
      return currentUser ? <Route {...props} /> : <Redirect to="/login" />;
    }
    

    这允许您使用所有普通的Route 组件道具,并且不限于使用 component 道具。

    用法:

    • <PrivateRoute path="/admin" component={Admin} />
      
    • <PrivateRoute path="/admin" render={props => <Admin {...props} />} />
      
    • <PrivateRoute path="/admin">
        <Admin />
      </PrivateRoute>
      

    【讨论】:

      【解决方案2】:

      我也遇到过同样的问题。这解决了我。用 Switch 包裹你的三个路由。

      <Switch>
          <Route path="/signup" component={Signup} />
          <Route path="/login" component={Login} />
          <Route path="/forgot-password" component={ForgotPassword} />
      </Switch>
      

      由于第一个私有路由有根路径,它总是会去路由。您可以将精确用于第一条私有路由。但最好的方法应该是放置第一个私有路由

      <PrivateRoute path={["/admin", "/"]} component={MainPage} />
      

      在底部。所以当没有匹配时它只会去那里。

      【讨论】:

        【解决方案3】:

        您没有在ProtectedRoute 中传递Route 的路径。

        <Route
              {...rest} // spread the test here
              render={(props) => {
                return currentUser ? <Admin {...props} /> : <Redirect to="/login" />; // it redirects when the user does not log in.
              }}
            ></Route>
        

        也像@Drew Reese 提到的那样切换路径的路线。

        【讨论】:

          猜你喜欢
          • 2018-09-20
          • 1970-01-01
          • 1970-01-01
          • 2016-11-05
          • 2018-02-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多