【问题标题】:Protecting Route based on whether user has access to根据用户是否有权访问来保护路由
【发布时间】:2021-04-03 16:36:42
【问题描述】:

我正在构建(我认为)应该是 React Router 上的简单访问保护,以根据用户是否有权访问该规范来保护路由 /spec/:id 上的给定 spec。用户对规范的访问由他们的id: string 是否出现在规范的shared: string[] 字段中来表示

当用户无权访问时,预期的行为是他们被重定向到/ 的主页。在下面的情况下,用户无权访问,而是留在/spec/:id,控制台中没有错误。谁能指出为什么会这样?非常感谢

import { useContext, useEffect, useState } from "react";
import { Redirect, Route, useParams } from "react-router-dom";
import { getSpecById } from "../Models/Spec";
import { AuthContext } from "../Util/Auth";

const ProtectedRoute = ({ component: Component, ...rest }: any) => {
  const { id } = useParams<{ id: string }>();
  const {currentUser} = useContext(AuthContext);
  const [isOwner, setIsOwner] = useState<boolean>(false);


  useEffect(() => {
    async function fetchOwnership() {
      const specData = await getSpecById(id);
      if (specData && currentUser) {
        console.log(specData.shared.includes(currentUser.uid)); //logs false
        setIsOwner(specData.shared.includes(currentUser.uid));
      }
    }
    fetchOwnership();
  });

  return (
    <Route
      {...rest}
      render={(routeProps: any) => {
        isOwner ? (
          <Component {...routeProps} />
        ) : (
          <Redirect to={"/"} />
        )
      }}
    />
    )
  };

export default ProtectedRoute

这是我打电话给&lt;ProtectedRoute&gt;

&lt;ProtectedRoute exact path="/spec/:id" render={() =&gt; (&lt;Spec isEdit={true}/&gt; )}/&gt;


编辑 根据 Jason 的反馈,我将包含isOwner 的状态变量重新设计为使用useRef()。但是Redirect 仍然没有被调用。即使isOwner 等于false,我也不会被送回"/"

const ProtectedRoute = ({ component: Component, ...rest }: any) => {
  const { id } = useParams<{ id: string }>();
  const {currentUser} = useContext(AuthContext);
  const isOwner = useRef(null);

  useEffect(() => {
    async function fetchOwnership() {
      const specData = await getSpecById(id);
      if (specData && currentUser) {
        isOwner.current = specData.shared.includes(currentUser.uid);
      }
    }
    fetchOwnership();
  });

  console.log(isOwner.current);

  if (isOwner.current === undefined) {
    return null;
  }

  return (
    <Route
      {...rest}
      render={(routeProps: any) => {
        isOwner.current ? (
          <Component {...routeProps} />
        ) : (
          <Redirect to={"/"} />
        )
      }}
    />
    )
  };

【问题讨论】:

    标签: reactjs typescript react-router


    【解决方案1】:

    似乎根本没有调用重定向。在第一次渲染中,isOwner 为 false(给 useState 的默认值),因此您应该立即被重定向(如果一切正常);

    我假设Route 标记没有呈现它的孩子。是否从{...rest} 获得了path 属性?

    【讨论】:

    • 是的,没错。我已经更新了 Q 以包括我调用它。很好的标注,即使它工作正常,我也会被重定向,有什么办法可以缓解这种情况并在我渲染路由之前检查数据库?
    • 当然,不要初始化isOwner,然后if (isOwner === undefined) return null;
    • 谢谢!是的,有道理。但你是对的,重定向甚至没有被调用,所以我仍然没有被发送回"/"
    【解决方案2】:

    你不能直接调用 useEffect 钩子里面的异步函数,你必须使用 IIFE 方法。这是我使用的一个示例。

    useEffect(() => {
     (async () => {
      const users = await axios.get("https://randomuser.me/api/?page=1&results=10&nat=us");
      setUsers(users.data.results);
     })();
    }, []);
    

    在你的情况下

    useEffect(() => {
        async function fetchOwnership() {
          const specData = await getSpecById(id);
          if (specData && currentUser) {
            console.log(specData.shared.includes(currentUser.uid)); //logs false
            setIsOwner(specData.shared.includes(currentUser.uid));
          }
        }()
        
      });
    

    【讨论】:

    • 在声明后立即调用命名函数和通过名称调用它没有区别
    猜你喜欢
    • 2013-06-17
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 1970-01-01
    • 2021-02-13
    • 1970-01-01
    • 2021-11-04
    相关资源
    最近更新 更多