首页 > 解决方案 > React Router 中的用户身份验证

问题描述

伙计们。我正在学习如何使用 React Router 将 React 与 Express 集成,并且在验证用户时遇到了问题。我正在尝试使用更高阶的组件根据用户的授权状态有条件地呈现受保护的路由。

const ProtectedRoute = ({ component: Component, ...rest }) => {
  return (
    <Route
      {...rest}
      render={props => {
        if (!AUTHORIZED) {
          return <Redirect to="/login" />;
        }
        return <Component {...props} />;
      }}
    />
  );
};

我遇到的问题在if (!AUTHORIZED)声明中。我正在使用 Passport 在 Express 服务器端处理身份验证,并且我设置了一个端点来检索用户信息和授权状态,但我无法弄清楚如何在页面呈现之前访问该数据。如果我使用类组件而不是功能组件(也学习钩子),我认为我可以使用componentWillMount生命周期方法获取数据,但我读到这是不好的做法。任何关于我如何从这里继续前进的想法将不胜感激!

***编辑*** 我试图让它工作的几件事......我尝试添加一个授权模块来为我获取数据。

class Auth {
  constructor() {
    this.authenticated = false;
  }

  async isAuthenticated() {
    console.log("hitting auth route");
    await fetch("/api/auth")
      .then(res => res.json())
      .then(json => {
        if (json.error) {
          this.authenticated = false;
        }
        this.authenticated = true;
      });
    return this.authenticated;
  }
}

export default new Auth();

我导入模块并auth.authenticated()代替 placeholder插入AUTHORIZED。这个函数被跳过了,因为它是异步的,并且重定向总是会发生。所以我需要添加awaitauth.authenticated(). 但是现在我需要async更进一步,所以我愚蠢地async在前面添加了props这样 render={async props => { 的内容:所以现在它试图渲染一个 Promise 对象而不是一个组件,并且我们一直得到错误Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. Promises。

标签: reactjsreact-router

解决方案


如果有人遇到类似问题,请回答这个问题......我的第一个解决方案是基于Firealem Erko的评论。登录时,我将带有用户 ID 的变量保存到本地存储并在我的组件中引用它。这是一个很好的第一个解决方案,但后来被他评论中提到的rotimi-best改进了。事实证明,您确实可以将 props 传递给这些组件,这是我没有经验的。所以这就是我现在的做法。最终解决方案如下:

const ProtectedRoute = ({
  component: Component,
  logged,
  setLogged,
  ...rest
}) => {
  return (
    <Route
      {...rest}
      render={props => {
        if (!logged) {
          return (
            <Redirect
              to={{
                pathname: "/login",
                state: { flashInfo: "Please log in to continue." }
              }}
            />
          );
        } else {
          return <Component {...props} logged={logged} setLogged={setLogged} />;
        }
      }}
    />
  );
};

这是我传递道具的父组件:

function App() {
  let [logged, setLogged] = useState(false);

  useEffect(() => {
    if (window.localStorage.getItem("qrs")) {
      setLogged(true);
    } else {
      setLogged(false);
    }
  }, []);

  return (
    <div className="App">
      <BrowserRouter>
        <Nav logged={logged} setLogged={setLogged} />
        <Switch>
          <ProtectedRoute
            exact
            path="/dashboard"
            component={Dashboard}
            logged={logged}
            setLogged={setLogged}
          />
          <Route
            path="/register"
            exact
            render={props => <Register {...props} logged={logged} />}
          />
          <Route
            path="/login"
            exact
            render={props => (
              <Login {...props} logged={logged} setLogged={setLogged} />
            )}
          />
        </Switch>
      </BrowserRouter>
    </div>
  );
}

感谢所有评论者的建议!


推荐阅读