返回JSX.Element的自定义防护

时间:2019-12-17 11:23:37

标签: reactjs typescript

我正在尝试实现一个简单的“防护”,该防护将我重定向到给定currentUsercurrentClub值的其他组件:

export const ClubDashboard: React.FC = () => {
  const { id } = useParams();
  const currentUser = useStoreState(state => state.currentUser.value);
  const currentClub = useStoreState(state => state.currentClub.value);
  return clubGuard(
    currentUser,
    currentClub,
    <div className="container vertical full-height-screen">
      <Link to={`/clubs/${currentClub!.id}/settings`}>
        <IoIosSettings className="icon absolute-top-right" />
      </Link>
      [...]
    </div>
    id);
}

这是我实现该功能的方式:

export const clubGuard = (
  currentUser: User | null,
  currentClub: Club | null,
  page: JSX.Element,
  urlClubId?: string | null,
  pageLoading?: boolean
): JSX.Element => {
  if (!currentUser) {
    return <Redirect to={"/login"} />;
  }
  if (!currentClub || (currentClub && currentClub.id !== urlClubId)) {
    return <Redirect to={"/"} />;
  }
  if (pageLoading) {
    return <PageLoading />;
  }
  return page;
};

但是,每当currentClub例如是null时,它甚至都不会进入clubGuard函数,而是直接提示错误:Uncaught TypeError: Cannot read property 'id' of null它在进入函数之前先扫描代码,这是正常现象吗?我想念什么吗?

1 个答案:

答案 0 :(得分:1)

这很可能是由于您要传递给函数的JSX。在传递给您的函数之前会对其进行评估(因为所有参数都是如此)。

<Link to={`/clubs/${currentClub!.id}/settings`}>  // <---- This template string is most likely the culprit
  <IoIosSettings className="icon absolute-top-right" />
</Link>

感叹号不进行任何空值检查,而是告诉Typescript您知道,它不能为空,并且Typescript不必担心它为空。实际上,它仍然可以为null,因为在运行时不进行任何检查。您可以阅读有关该here的更多信息。

简单的解决方案是进行空检查。

<Link to={`/clubs/${!!currentClub ? currentClub.id : 0}/settings`}> 
  <IoIosSettings className="icon absolute-top-right" />
</Link>