reactjs 在哪里保留应用装载获取逻辑和复杂的React v6路由?

5ssjco0h  于 2022-12-12  发布在  React
关注(0)|答案(1)|浏览(112)

我有一个受保护的路由组件,它主要处理以下几项任务:

  • 使用Auth0授权用户。
  • 检查存储是否为空,然后向后端API请求用户数据。
  • 传递函数,将访问令牌返回给axios拦截器,以便所有请求都有一个承载令牌附加到其头部。
  • 现在,我需要添加更多的API请求,以便在应用加载时获取数据。

是否可以将所有这些逻辑都放在受保护的路由组件中?

受保护路由.tsx

const ProtectedRoute = () => {
  const dispatch = useAppDispatch();
  const location = useLocation();
  const { isAuthenticated, isLoading, getAccessTokenSilently } = useAuth0();
  const user = useAppSelector((state) => state.user);

  useEffect(() => {
    const fetchUser = async () => {
      try {
        await dispatch(getUser()); // here will be more dispatches for fetching data from backend
      } catch (e) {}
    };

    if (isAuthenticated && !user) {
      fetchUser();
    }
  }, [dispatch, isAuthenticated, user]);

  useEffect(() => {
    const getAccessToken = async () => {
      try {
        const token = await getAccessTokenSilently();
        return Promise.resolve(token);
      } catch (e) {
        console.log('getAccessToken error:', e);
      }
    };
    httpService(getAccessToken);
  }, [getAccessTokenSilently]);

  if (isLoading || (!user && isAuthenticated)) {
    return <Loader areaLoader />;
  }

  if (isLoading) {
    return <Loader areaLoader />;
  }

  return isAuthenticated ? <Outlet /> : <Navigate to="/auth" state={{ from: location }} replace />;
};

在App.tsx中,我有一个巨大的路由器,在我看来,放置所有这些逻辑的唯一地方是受保护的路由组件,或者可能是BaseLayout组件:

const router = createBrowserRouter([
  {
    element: <AuthProvider />,
    children: [
      {
        element: <ProtectedRoute />,
        children: [
          {
            element: <BaseLayout />,
            children: [
              {
                index: true,
                element: <ProjectsPage />,
              },
              {
                path: PATHS.faces,
                element: <FacesPage />,
              },
              {
                path: PATHS.files,
                element: <FilesPage />,
                children: [
                  // some children
                ],
              },
              // some other routes
            ],
          },
        ],
      },
      {
        path: PATHS.auth,
        element: <AuthPage />,
      },
    ],
  },
]);

基本布局.tsx

const BaseLayout = () => {
  return (
    <Stack direction={'row'} gap={32}>
      <Sidebar />
      <Box>
        <Outlet />
      </Box>
    </Stack>
  );
};

我尝试将获取数据逻辑移到App.tsx,但没有获取任何数据。我认为是因为这个原因(isAuthenticated来自Auth0钩子,当App.tsx加载时它为false):

if (isAuthenticated && !user) {
  dispatch(fetchUser());
  dispatch(fetchRawMedias());
}

React Router v6加载程序出现问题

AuthProvider在页面上对Auth0发出重新加载请求以获取令牌。然后令牌附加到所有标头请求。问题是在页面重新加载时,React Router加载程序在Auth0之前触发...它发送标头中没有令牌的请求。如何处理此问题?

ee7vknir

ee7vknir1#

对于这样的情况,我通常会采用与声明变量相同的做法,即尽可能地将声明 * 下移 * 以限制它们的作用域。
示例

  • 如果只有一个函数需要该变量,则在函数中本地声明该变量。
  • 如果一个对象/类中的多个函数/方法需要该变量,则在对象/类中局部声明。

在何处声明React状态函数类似地取决于状态的作用域和需要访问它的对象。

  • 如果只有1个React组件需要该状态,则在组件中本地声明该状态。
  • 如果几个兄弟组件需要该状态,则在最近的公共祖先组件中声明该状态并向下传递。
  • 如果“生产”和“消费”组件之间的距离变得很大,则将状态移到React上下文中。

这里的想法是将声明 * 向上推**到必要的程度*。
那么,“正确的地方”在哪里呢?
保持获取逻辑和状态的“正确”位置是在满足需求的情况下尽可能限制其范围的位置。随着用例和特性的变化,这可能会在应用程序的生命周期中发生变化。
如果你有“全局应用状态”,应该在应用挂载时获取和管理,这听起来像是它应该/应该位于应用的ReactTree中相当高的位置。
是否可以将所有这些逻辑都放在受保护的路由组件中?
这个问题的答案是,你 * 可以 * 这样做,但我建议创建一个新的提供者/布局组件,专门用于状态管理和数据获取,主要是出于希望保持良好的“关注点分离”和single responsibility principle。换句话说,我不建议让ProtectedRoute做更多的事情,而不仅仅是保护路由,或者让BaseLayout做更多的UI布局。
提供程序组件和放置示例:
第一个

相关问题