尝试使用react钩子进行经过身份验证的路由,下面的代码段在刷新页面时出现,而令牌可用时,它在第一次渲染时不会在useEffect中被拾取。我在这里做错了



const AuthRoute = ({ component: Component, ...rest }) => {
  const context = useContext(AuthStateContext)
  const token = window.localStorage.getItem('token')

  useEffect(() => {
    if (token) {
      context.setLogin()
    }
    console.log("TOKEN ->", token)
  }, [])
  return (
    <Route
      {...rest}
      render={props => (
        context.isAuthenticated ?
          <Component {...props} />
          : <Redirect to={{
            pathname: "/",
            state: { from: props.location }
          }} />
      )}
    />
  )
}

最佳答案

我假设context.setLogin()会将context.isAuthenticated设置为true。如果是这样,那就说明了。

每次渲染后,总是异步调用useEffect(callback)的回调函数。从第一次渲染开始,仅在读取setLogin()的值后调用isAuthenticated,该值在访问时应为false

因此,渲染逻辑转到第二个分支<Redirect />,该分支立即将用户带到其他地方。

为此,您可以推迟确定isAuthenticated的呈现util状态。

(在这里,我假设您想在渲染树中尽早检查并设置isAuthenticated,然后通过isAuthenticated对象广播AuthStateContext,以使应用程序的其他部分引起注意。)

我建议这种模式:

const AuthRoute = ({ component: Component, ...rest }) => {
  const context = useContext(AuthStateContext)
  const [authChecked, setAuthChecked] = useState(false)

  useEffect(() => {
    const token = window.localStorage.getItem('token')
    if (token) context.setLogin()
    setAuthChecked(true)
    console.log("TOKEN ->", token)
  }, [])

  if (!authChecked) return null  // <-- the trick!

  return (
    <Route
      {...rest}
      render={props => (
        context.isAuthenticated ?
          <Component {...props} />
          : <Redirect to={{
            pathname: "/",
            state: { from: props.location }
          }} />
      )}
    />
  )
}


旁注,如果context.setLogin()仅异步设置isAuthenticated的状态,则您需要添加回调或promise模式,例如

context.setLogin(() => setAuthChecked(true))
// or
context.setLogin().then(() => setAuthChecked(true))

关于javascript - 使用React,React Hooks的私有(private)路由,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60861816/

10-09 14:39