javascript - 使用 React、React Hooks 的私有(private)路由

标签 javascript reactjs

尝试使用 react Hook 创建经过身份验证的路由,使用下面的代码片段,当我在 token 可用时刷新页面时,它会出现在第一次渲染时不会在 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.isAuthenticatedtrue 。如果是这样的话,那就解释得通了。

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

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

要实现此目的,您可以推迟 isAuthenticated 的渲染 util 状态已决定。

(在这里,我假设您想要在渲染树中尽早检查并设置 isAuthenticated 一次,然后将 isAuthenticatedAuthStateContext 对象广播到应用程序的其他部分注意。)

我建议这种模式:

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/

相关文章:

javascript - 如何将表单验证错误更改反射(reflect)到 CSS?

javascript - 使用 Jest 测试 React 组件的方法

reactjs - CORS 未获取 header 的 Fetch Post 问题

javascript - 值/占位符 - 单词的不同样式

javascript - 谷歌地图 div 区域中仅显示带有缩放控制的白色

javascript - 如何将javascript数组发送到php?

javascript - 尽管使用目标 ="_blank",但 React Markdown 链接不会在新选项卡中打开

javascript - 检查具有一定宽度的div

javascript - jquery中如何延迟焦点事件?

javascript - 使用 typescript jsx 的 ESLint 配置