未验证用户时,反应闪烁的专用路由

时间:2020-07-22 22:46:53

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

我正在使用from api.api import app from flask_script import Manager from api.connector import engine, BaseModel from api.detector.route import Detector manager = Manager(app) app.config['DEBUG'] = True @manager.command def create_tables(): "Create relational database tables." BaseModel.metadata.create_all(engine) if __name__ == '__main__': manager.run() 保护整个应用程序。所有路由均受ProtectedRoute组件(请参见下面的代码)保护,该组件将重定向到外部URL,如果用户未登录,则为单点登录(SSO)页面。

问题:

当用户转到“ / home”时,在获得重定向到“ external-login-page.com /”(登录页面)之前,他们会简要了解(受保护的)路由。如何避免闪烁,以便用户仅看到登录页面?

react-router-dom

4 个答案:

答案 0 :(得分:2)

可以更早调用

window.location.href以防止闪烁。同样,在您的特定情况下,您可能想要的是在未验证用户身份时完全不呈现任何内容。

代码可能看起来像这样:

export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
  isAuthenticated,
  ...rest
}) => {
  if (!isAuthenticated) { // redirect if not logged in
    window.location.href = 'http://external-login-page.com/';
    return null;
  } else {
    return <Route {...rest} />;
  }
};

答案 1 :(得分:1)

您可以考虑使用Redirect组件

export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
  isAuthenticated,
  ...rest
}) => {
  if (!isAuthenticated) { 
    return <Redirect to='https://external-login-page.com/' />
  } else {
    return <Route {...rest} />;
  }
};

我猜想直接调用window + return null会在页面重新加载之前一瞬间渲染React应用。

答案 2 :(得分:1)

您可以像这样简单地使用重定向组件。

  export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
      isAuthenticated,
       children,
      ...rest
    }) => {
         return <Route {...rest} render={() => isAuthenticated ? children : <Redirect to='http://external-login-page.com/' />}
    }

答案 3 :(得分:0)

发布最终适用于我的解决方案:而不是被Router阻止,而被App阻止。

关键是将App分成两个部分,AuthenticatedAppUnauthenticatedApp。从那里,根据用户的访问级别,延迟加载正确的组件。这样,如果没有获得授权,他们的浏览器甚至根本不会加载AuthenticatedApp

  • AuthenticatedApp是整个应用程序,提供程序,路由器等的组成部分。无论您最初在App.tsx中拥有什么,都应该放在这里。
  • UnauthenticatedApp是一个组件,您希望用户在不允许他们访问应用程序时看到它们。诸如“未经授权。请与管理员联系以寻求帮助。”

App.tsx

const AuthenticatedApp = React.lazy(() => import('./AuthenticatedApp'));
const UnauthenticatedApp = React.lazy(() => import('./UnauthenticatedApp'));

// Dummy function to check if user is authenticated
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
const getUser = () => sleep(3000).then(() => ({ user: '' }));

const App: React.FC = () => {
  // You should probably use a custom `AuthContext` instead of useState,
  // but I kept this for simplicity.
  const [user, setUser] = React.useState<{ user: string }>({ user: '' });

  React.useEffect(() => {
    async function checkIfUserIsLoggedInAndHasPermissions() {
      let user;
      try {
        const response = await getUser();
        user = response.user;
        console.log(user);
        setUser({ user });
      } catch (e) {
        console.log('Error fetching user.');
        user = { user: '' };
        throw new Error('Error authenticating user.');
      }
    }
    checkIfUserIsLoggedInAndHasPermissions();
  }, []);

  return (
    <React.Suspense fallback={<FullPageSpinner />}>
      {user.user !== '' ? <AuthenticatedApp /> : <UnauthenticatedApp />}
    </React.Suspense>
  );
};

export default App;

在[0]上阅读Kent C Dodd的精彩文章!

编辑:用相似的方法找到了另一个很好的例子,有点复杂-[1]

[0] https://kentcdodds.com/blog/authentication-in-react-applications?ck_subscriber_id=962237771 [1] https://github.com/chenkie/orbit/blob/master/orbit-app/src/App.js

相关问题