授权路线与未授权路线 reactjs 未正确加载

IT技术 javascript reactjs
2021-05-13 05:17:45

我无法理解为什么我的AuthorizedvsUnauthorized路由运行不正常.. 以下是我的路由设置方式:

class App extends Component {

  render() {
    return (
      <HashRouter>
          <React.Suspense fallback={loading()}>
            <Switch>
              <UnauthenticatedRoute exact path="/login" name="Login Page" component={Login} />
              <Route exact path="/register" name="Register Page" component={Register} />
              <Route exact path="/404" name="Page 404" component={Page404} />
              <Route exact path="/500" name="Page 500" component={Page500} />
              <AuthenticatedRoute path="/" name="Home" component={DefaultLayout} />
            </Switch>
          </React.Suspense>
      </HashRouter>
    );
  }
}

export default App;

我有一个auth.js包含所有这些路由类型以及检查 JWT 令牌是否有效的方法:

import React from 'react';
import { Redirect, Route } from 'react-router-dom';
import { Api } from './api'

const isAuthenticated = () => {
  Api.isActiveToken(sessionStorage.getItem('token')).then(
    (response) => {
      console.log(response)
      return response.ok
    },
    (error) => {
      return false
    }
  )
}

const AuthenticatedRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => (
    isAuthenticated()
      ? <Component {...props} />
      : <Redirect to='/login' />
  )} />
);

const UnauthenticatedRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => (
    !isAuthenticated()
      ? <Component {...props} />
      : <Redirect to='/' />
  )} />
);

export { AuthenticatedRoute, UnauthenticatedRoute }

console.log(response)看来,这样的:

Response {type: "cors", url: "http://xxx/api/v1/login/validate-token", redirected: false, status: 200, ok: true, …}
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://xxx/api/v1/login/validate-token"
__proto__: Response

sessionStorage拿着令牌就好了。我做错了什么,以至于我的路线永远不会重定向/允许我转到AuthorizedRoute?

2个回答

isAuthenticated()是异步的,当前返回 void。你必须让 isAuthenticated 返回一个布尔值的Promise。

一旦您让 isAuthenticated 返回一个值,您就需要使用效果和状态从Promise中提取实际值。

import React, { useState, useEffect } from 'react';
import { Redirect, Route } from 'react-router-dom';
import { Api } from './api';

const isAuthenticated = async () => {
  try {
    const response = await Api.isActiveToken(sessionStorage.getItem('token'));
    return response.ok;
  } catch (error) {
    return false;
  }
};

const AuthenticatedRoute = ({ component: Component, ...rest }) => {
  const [authenticated, setAuthenticated] = useState(null);
  useEffect(() => {
    isAuthenticated().then((bool) => setAuthenticated(bool));
  }, []);

  return (
    <Route
      {...rest}
      render={(props) => {
        if (authenticated === null) return '...loading';
        return authenticated ? <Component {...props} /> : <Redirect to="/login" />;
      }}
    />
  );
};

const UnauthenticatedRoute = ({ component: Component, ...rest }) => {
  const [authenticated, setAuthenticated] = useState(null);
  useEffect(() => {
    isAuthenticated().then((bool) => setAuthenticated(bool));
  }, []);
  return (
    <Route
      {...rest}
      render={(props) => {
        if (authenticated === null) return '...loading';
        return !authenticated ? <Component {...props} /> : <Redirect to="/" />;
      }}
    />
  );
};

export { AuthenticatedRoute, UnauthenticatedRoute };

我认为问题在于Switch组件需要某些类型的子组件,而您传递给它的组件类型不同AuthenticatedRoute,它可能无法处理。您可以将组件转换为仅返回Route元素的渲染函数,以便Switch仅包含路由,而不是创建新的组件类型

const renderAuthenticatedRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => (
    isAuthenticated()
      ? <Component {...props} />
      : <Redirect to='/login' />
  )} />
);

const renderUnauthenticatedRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => (
    !isAuthenticated()
      ? <Component {...props} />
      : <Redirect to='/' />
  )} />
);

class App extends Component {
  render() {
    return (
      <HashRouter>
          <React.Suspense fallback={loading()}>
            <Switch>
              { 
                renderUnauthenticatedRoute({ 
                  exact: true, 
                  path: "/login", 
                  name: "Login Page",
                  component: Login
                })
              }
              <Route exact path="/register" name="Register Page" component={Register} />
              <Route exact path="/404" name="Page 404" component={Page404} />
              <Route exact path="/500" name="Page 500" component={Page500} />
              { 
                renderAuthenticatedRoute({
                  path: "/",
                  name: "Home",
                  component: DefaultLayout
                }) 
              }
            </Switch>
          </React.Suspense>
      </HashRouter>
    );
  }
}