React JS中的异步路由元素返回

3

出现错误: Guard(...): 从渲染中没有返回任何内容。这通常意味着缺少一个返回语句。

我希望在将元素返回给路由元素之前,在我的守卫组件中调用API以检查已登录用户是否具有访问特定路由的权限。

为此,我实现了一个守卫。以下是路由文件代码。

export default function Router() {
    return (
        <Routes>
            <Route path="organizations">
                <Route path="list" element={<Guard><ListOrganization /></Guard>} />
        </Routes >
    );
}

守卫组件代码

const Guard = (props) => {
    fetch('https://apiToCheckPermission.com')
    .then(response => {
        if (response.isPermission) {
            return props.children;
        }
    })
};

export default Guard;

我想实现异步路由元素,但如果我不立即从守卫(Guard)返回元素,React就会报错。

请问有谁可以告诉我如何解决这个错误?

2个回答

2
尝试定义一个状态来处理权限,并使用useEffect来加载数据:
const Guard = (props) => {
  const [hasPermission, setHasPermission] = useState(false);

  useEffect(() => {
    const fetchPermission = async () => {
        const response = await fetch('https://apiToCheckPermission.com');
        setHasPermission(response.isPermission);
    }
    
    fetchPermission().catch(console.error);
  }, []);

  if (!hasPermission) return <>Unauthorized</>;

  return props.children;
};

export default Guard;

你是否正在导入 useStateuseEffect - lpizzinidev
这取决于响应的结构。尝试设置 setHasPermission(response.isPermission); - lpizzinidev
2
useEffect 钩子的回调函数绝对不能是一个 async 函数。这将隐式返回一个 Promise 对象,React 将尝试将其用作 useEffect 钩子的清理函数。只需将异步回调抽象成在回调中调用的内部函数,或在 useEffect 钩子外部声明并在回调中调用即可。 - Drew Reese

2

如果Guard应该是一个React组件,那么它需要始终返回有效的JSX。当前Guard什么都不返回。即它需要从Promise链中返回一些内容,然后再从函数体中返回。

要解决此问题,可以使用一些本地状态来保存已确认/验证的权限值,并有条件地渲染children属性或备用方案。典型的路由保护实现将等待确认用户的访问权限,然后渲染children,或将其重定向到登录页面并记录所访问的位置,以便在认证后将用户重定向回来。

示例:

const Guard = ({ children }) => {
  const location = useLocation();

  const [hasPermission, setHasPermission] = React.useState(); // <-- initially undefined

  React.useEffect(() => {
    );
    fetch('https://apiToCheckPermission.com')
      .then(response => {
        setHasPermission(response.isPermission);
      });
  }, []);

  if (hasPermission === undefined) {
    return null; // or loading indicator, spinner, etc
  }

  return hasPermission
    ? children
    : <Navigate to="/login" replace state={{ from: location }} />;
};

但这不是异步路由。在我从API获取响应之前,我将返回另一个组件。我不想向用户显示另一个组件。 - Chris T
@ChrisT 在异步代码运行时,您想向用户显示什么?在我的示例中,我返回null以便在权限检查完成之前不渲染任何内容。我不确定您所说的“异步路由”,路由匹配和渲染是完全同步的。React组件渲染也是完全同步的。 - Drew Reese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接