You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router 6.15.0加载器请求数据时页面完全空白问题求助

问题分析与解决

问题原因

你使用createBrowserRouter时,它默认会在渲染任何路由组件前,先执行所有匹配路由的loader函数。首页子路由配置的getApplications loader会在初始访问时先发起请求,只有等请求完成后才会渲染RootLayout和HomePage,这就导致了加载期间页面完全空白。

而你之前课程中的实现大概率采用了不同的路由模式(比如旧版BrowserRouter+Routes,未使用data loader),或者使用了defer延迟数据加载逻辑,让组件先渲染再加载数据。


修复方案

方案1:使用defer让组件先渲染,再异步加载数据

通过defer包装异步数据,让路由立即渲染组件,而非等待请求完成:

  1. 更新applicationLoader.js
import { defer } from 'react-router-dom';

const getApplications = async () => {
  const token = localStorage.getItem('token');

  try {
    // 将请求逻辑封装为异步函数,defer会立即返回,不阻塞组件渲染
    const fetchApplications = async () => {
      const response = await axios.get(appsEndPoint(), {
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `token ${token}`
        },
        timeout: 30000
      });
      return response.data;
    };

    return defer({ applications: fetchApplications() });
  } catch (error) {
    if (isAxiosError(error)) {
      console.log(error);
      toast.error(error.message);
      return defer({ applications: Promise.reject(error) });
    }
  }
};

export default getApplications;
  1. 更新HomePage.js处理异步状态
import { useLoaderData, useAsyncValue, useAsyncError } from 'react-router-dom';

const HomePage = () => {
  const { applications } = useLoaderData();
  const data = useAsyncValue(applications);
  const error = useAsyncError(applications);

  // 数据加载中
  if (data === undefined) {
    return <LoadingSpinner />;
  }

  // 加载出错
  if (error) {
    return <div>加载失败,请稍后重试</div>;
  }

  console.log(data);

  return (
    <>
      <PageHeader pageTitle='Αιτήσεις' hasBack={false} />
    </>
  );
};

export default HomePage;
  1. 调整RootLayout.js确保初始渲染
const RootLayout = () => {
  const navigate = useNavigate();
  const navigation = useNavigation();
  const token = localStorage.getItem('token');
  const isPageLoading = navigation.state === 'loading';

  useEffect(() => {
    if (!token) {
      navigate('/login');
    }
  }, [token, navigate]);

  // token不存在时返回占位,避免空白
  if (!token) {
    return null;
  }

  return (
    <Layout>
      <Navbar />
      <Layout>
        <PageContent>
          <Outlet /> {/* 加载状态交给HomePage处理,也可保留原isPageLoading判断 */}
        </PageContent>
        <PageFooter />
      </Layout>
    </Layout>
  );
};

方案2:启用React Router未来特性,用startTransition处理加载

在创建router时启用future.v7_startTransition,让loader在后台运行,同时渲染组件,此时useNavigation().state会正确显示loading状态:

const router = createBrowserRouter(
  [
    // 你的路由配置
  ],
  {
    future: {
      v7_startTransition: true,
    },
  }
);

启用后,RootLayout中的isPageLoading判断会生效,加载期间会正常显示RootLayout和加载动画。


额外优化

  • 确保RootLayout在任何情况下都有返回值,避免token不存在时页面空白(比如返回null或加载组件)。
  • 可在RootLayout中统一处理路由加载状态,无需在子组件中重复编写加载逻辑。

内容的提问来源于stack exchange,提问作者Jim Zokas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 23:32:13