【问题标题】:Trouble with react private routes反应私有路由的问题
【发布时间】:2021-07-12 21:24:18
【问题描述】:

我正在尝试创建受保护的路线。如果用户登录与否,我有一个反应上下文返回true or false

问题是,即使我通过了身份验证,我仍然无法访问仪表板路由(即使我已登录,它也会重定向到登录)。我认为这是因为我向我的服务器发送了一个 api 请求以检查用户是否经过身份验证,并且当时上下文值为 undefined

我试图通过在渲染路由之前检查上下文是否未定义来解决这个问题,但它仍然不起作用。

App.js

const ctx = useContext(userContext);
  console.log(ctx.authed); // return true or false

  return (
    <div className='App'>
      <Router>
        <Switch>
          <Route path='/' exact component={HomePage}></Route>
          <Route exact path='/auth/register' component={Register}></Route>
          <Route exact path='/auth/login' component={Login}></Route>

          {!ctx.loading ? (
            <ProtectedRoute
              path='/dashboard'
              isAuth={ctx.authed}
              exact
              component={Dashboard}
            />
          ) : null}
        </Switch>
      </Router>
    </div>
  );

ProtectedRoute.js

function ProtectedRoute({ isAuth, component: Component, ...rest }) {
  return (
    <Route
      {...rest}
      render={(props) => {
        if (isAuth) {
          return <Component />;
        } else {
          return (
            <Redirect to={{ pathname: '/login', 
            state: { from: props.location } }} />
          );
        }
      }}
    />
  );
}

我的上下文看起来像:

export const userContext = createContext({});
export default function Context(props) {
  const [authed, setAuthed] = useState(undefined);
  const [loading, setLoading] = useState(false);

  const fetchData = async () => {
    setLoading(true);
    await axios({
      method: 'GET',
      withCredentials: true,
      credentials: 'include',
      url: '/checkAuthentication',
    }).then((res) => {
      setAuthed(res.data.authenticated);
      setLoading(false);
    });
  };

  useEffect(() => {
    fetchData();
  }, []);

  return (
    <userContext.Provider value={{ loading, authed }}>
      {props.children}
    </userContext.Provider>
  );
}

我已经坚持了一段时间,我将不胜感激。谢谢!

【问题讨论】:

  • 当您在受保护的路由中 console.log isAuth 时会看到什么?
  • const [loading, setLoading] = useState(false); loading 开始为 false,在触发 useEffect 后的未来渲染中设置为 true,这可能意味着它仍然最初渲染 ProtectedRoute 并在加载用户之前进行重定向.如果您打算使用 useEffect 立即加载,为什么不将加载初始化为 true?
  • @azium isAuth 首先记录 undefined 但当 api 返回时它会更改为 true
  • 您的render 块在更改为true 时不会再次被调用吗?
  • 您如何导航到仪表板?你在某处有Link 组件,还是在你的登录组件中调用navigatehistory.push

标签: javascript reactjs react-router react-context


【解决方案1】:

您可以使用 useEffect 挂钩来找出 react 何时更改了您的 authed 变量。发生这种情况时,您可以检查用户是否已登录。如果没有,您可以使用history.push('/login')。你可以从react-router-domuseHistory钩子中得到history。在您的登录页面中,您可以使用上下文的加载变量来显示任何加载组件。

通过这种方法,您无需使用难以管理并降低代码可读性的冗余组件。

你的代码的问题是,当组件被挂载时,上下文的loading变量总是假的,此时authed的值是undefined。这就是为什么&lt;ProtectedRoute /&gt; 总是呈现并将您重定向到登录页面的原因。

【讨论】:

  • 这有帮助。基本上我设置了一个 useEffect 来检查 ctx.authed 是否未定义,如果不是,我将它传递到受保护的路由上。我在问题的底部添加了一个代码块,显示我做了什么,谢谢!
  • @user 不要将答案添加到您的问题中,而是将其作为实际答案发布在下面。
【解决方案2】:

@Alyks 解决方案帮助了我。除了添加了 useEffect 块外,没有任何变化。

  const ctx = useContext(myContext);
  const [isAuth, setIsAuth] = useState(ctx.authed);

  useEffect(() => {             //
    if (ctx.authed) {           //
      setIsAuth(ctx.authed);   <-- added this
    }                           //
  }, [ctx.authed]);             // 

  return (
    <div className='App'>
      <Router>
        <a href='/dashboard'>Dashboard</a>
        <a href='/auth/login'>Login</a>
        <Switch>
          <Route path='/' exact component={HomePage}></Route>
          <Route exact path='/auth/register' component={Register}></Route>
          <Route exact path='/auth/login' component={Login}></Route>

          {!ctx.loading ? (
            <ProtectedRoute
              path='/dashboard'
              isAuth={isAuth}
              exact
              component={Dashboard}
            />
          ) : null}
        </Switch>
      </Router>
    </div>
  );

【讨论】:

    猜你喜欢
    • 2018-11-05
    • 2022-01-11
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 2020-03-04
    • 2021-01-03
    相关资源
    最近更新 更多