繁体   English   中英

React-Router 比赛条件

[英]React-Router Race Condition

我正在尝试实施受保护的路线。 问题是,导航发生在setSession更新之前,这意味着authContext仍然是 false,受保护的路由组件将用户发送回/sign-in

这是我登录表单上的handleSubmit function

    const handleSubmit =
      async (e) => {
        e.preventDefault();

        let { data, error } = 
          await auth.signIn({
            email,
            password
          })

        if (error)
          setAuthError(error.message);

        if (data)
          navigate('/dashboard');
      }

这是我上下文中的signIn function,由上面的 function 调用

async ({ email, password }) => {
        let { data, error } =
          await client.auth.signInWithPassword({
            email,
            password
          })

        if (data)
          setSession(data.user)

        return { data, error }
      },

...当然,受保护的路由组件本质上是

let { isSignedIn } = useContext(AuthContext);
    
    return (
      isSignedIn
        ? children
        : <Navigate to="/sign-in" replace />
    )

环顾四周,这似乎是受保护路由教程的基本结构:使用处理程序 function 在上下文中调用登录 function; 上下文设置一些 state 并返回; 处理程序 function 然后导航。

我正在使用 React-Router 6.8.0。 有趣的是,导航中的登录/退出按钮(不在反应路由器<Outlet/>下似乎有效)

我认为您需要一个单独的 state 来管理何时检查身份验证状态。 目前您的逻辑并未涵盖该场景,例如,类似 -

let { isSignedIn, isAuthLoading } = useContext(AuthContext);

   if(isAuthLoading) return <Loading />
    
    return (
      isSignedIn
        ? children
        : <Navigate to="/sign-in" replace />
    )

或者您认为最适合您的应用程序结构的任何方式,但本质上,您需要有某种方式来处理代表您检查用户是否已通过身份验证或在身份验证期间表示的状态,然后您可以使用现有的私人路线当您知道用户是否登录时的逻辑。

据我所知,这是由于“批处理” - https://github.com/reactwg/react-18/discussions/21 ,解决方法是在setSession state 调用周围使用flushSync

React 异步应用setSession调用,在这种情况下,state 在<ProtectedRoute/>组件被命中时(在我们使用navigate('/dashboard')之后)仍然没有更新,所以isSignedIn仍然是false 所以我们被送回/sign-in

我猜这些“受保护的路由”教程中的大多数都使用 React < 18,其中在事件处理程序之外没有对setState调用进行批处理,即在 promises 内部,这意味着它们同步更新,因此上述模式在不使用flushSync的情况下工作.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM