React / firebase 应用程序在身份验证完成之前闪烁登录屏幕

Mat*_*065 4 javascript firebase reactjs react-router react-hooks

当您注册/登录/刷新页面时,登录页面会在转到正确页面之前闪烁。我尝试放入加载程序,但它所做的只是在闪烁然后转到正确页面之前执行加载程序动画。知道如何避免这种情况发生吗?

function App(){
  const [user, setUser] = useState();
  const [loading, setLoad] = useState(true);
  useEffect(() => {
    const unsubscribe = onAuthStateChanged(getAuth(), setUser, setLoad(false))
    return () => {unsubscribe()}
  }, [])
const AuthenticatedRoute = ({children}) => {
  let isAuthenticated;
    if(user !=null){
      isAuthenticated = true;
    }else{
      isAuthenticated = false;
    }
    if(!loading){
      return isAuthenticated? children: <Navigate to="/signin"/>
    }else{
      return <Loading/>
    }
  
}

const UnauthenticatedRoute = ({children}) => {
  let isAuthenticated;
    if(user !=null){
      isAuthenticated = true;
    }else{
      isAuthenticated = false;
    }
    if(!loading){
      return !isAuthenticated? children: <Navigate to="/home"/>
    }else{
      return <Loading/>
    }
  
}

      return(
      <Router>
      <div className="App">
          {
          <Routes>
            <Route exact path="/" element={<UnauthenticatedRoute><PreHome/></UnauthenticatedRoute>}/>
            <Route path='/home' element={<AuthenticatedRoute><Home/></AuthenticatedRoute>} />
            <Route exact path="/signin" element={<UnauthenticatedRoute><Signin/></UnauthenticatedRoute>} />
            <Route exact path="/signup" element={<UnauthenticatedRoute><Signup/></UnauthenticatedRoute>} />
          </Routes>
          }
      </div>
      </Router>
      )
  }
Run Code Online (Sandbox Code Playgroud)

注销代码:这一行一直用于注销

<button onClick={() => signOut(getAuth())}>Sign Out</button>
Run Code Online (Sandbox Code Playgroud)

登录代码:

async function OnFormSubmit(e){
        e.preventDefault();
        const auth = getAuth();
        try{
            isLoading(true);
            await signInWithEmailAndPassword(auth, email, pw)
            isLoading(false);
        }catch(err){
            console.log(err)
        }
    }
Run Code Online (Sandbox Code Playgroud)

Dre*_*ese 5

问题

  1. 仅当出现错误时才会清除加载状态onAuthStateChanged
  2. 路由保护器组件在另一个 React 组件内声明。这是反模式。当每次父App组件重新渲染时声明这些组件的新“实例”时,它将卸载/挂载组件的 subReactTree。
  3. 在决定重定向或呈现路由内容之前,组件不会等待用户的身份验证状态解析。

解决方案

  • 将路径保护器组件自行移出。渲染 anOutlet用于要渲染到的嵌套路由。这允许您将它们渲染为布局路由而不是单独的包装器组件。
  • 使用正确的“加载”状态。使用未定义user状态作为“加载状态”。

例子:

import { Outlet, Navigate } from 'react-router-dom';

const AuthenticatedRoute = ({ user }) => {
  if (user === undefined) return <Loading />;

  return user
    ? <Outlet />
    : <Navigate to="/signin" />;
};

const UnauthenticatedRoute = ({ user }) => {
  if (user === undefined) return <Loading />;

  return user
    ? <Navigate to="/home" />
    : <Outlet />;
};
Run Code Online (Sandbox Code Playgroud)

...

function App(){
  const [user, setUser] = useState();

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(getAuth(), setUser);
    return unsubscribe;
  }, []);

  return(
    <AuthContextProvider>
      <Router>
        <div className="App">
          <Routes>
            <Route element={<UnauthenticatedRoute user={user} />}>
              <Route path="/" element={<PreHome />} />
              <Route path="/signin" element={<Signin />} />
              <Route path="/signup" element={<Signup />} />
            </Route>
            <Route element={<AuthenticatedRoute user={user} />}>
              <Route path='/home' element={<Home />} />
            </Route>
          </Routes>
        </div>
      </Router>
    </AuthContextProvider>
  );
}
Run Code Online (Sandbox Code Playgroud)