8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

React Router 6.15.0 在加载程序获取数据时根本不渲染任何内容

Harish raj 2月前

30 0

在我使用 Vite 的 React 应用程序中,我使用 react-router 创建了一个基本路由器,其中有一个父元素渲染我的根布局,里面有一个 Outlet,以及在第一个子元素上有一个加载器...

在我使用 Vite 的 React 应用程序中,我创建了一个基本路由器,使用 react-router 父元素渲染根布局 Outlet ,并在父路由的第一个子元素上放置加载器。问题是,当我在子元素上导航时,应用程序根本不会渲染任何内容,只会呈现一个白屏,直到加载器完成数据获取。我的应用程序结构如下所示。

App.js

const router = createBrowserRouter([
  {
    path: '/',
    element: <RootLayout />,
    children:
    [
      {
        index: true,
        element: <HomePage />,
        loader: getApplications
      },
      {
        path: 'application/:applicationID',
        element: <h2>Single application page</h2>,
      }
    ]
  },
  {
    path: '/login',
    element: <LoginPage />,
    action: userLogin
  }
]);

const App = () => {
  return (
    <>
      <ToastContainer
        position='top-right'
        autoClose={5000}
        hideProgressBar={true}
        newestOnTop={true}
        closeOnClick={true}
        rtl={false}
        pauseOnFocusLoss
        draggable
        pauseOnHover
        theme='colored'
      />
      <RouterProvider router={router} />
    </>
  );
};

export default App;

Root.js

const RootLayout = () => {
  const navigate = useNavigate();

  const navigation = useNavigation();

  const token = localStorage.getItem('token');

  const isPageLoading = navigation.state === 'loading';

  console.log(isPageLoading);

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

  if (token) {
    return (
      <Layout>
        <Navbar />

        <Layout>
          <PageContent>
            {isPageLoading
              ? <LoadingSpinner />
              : <Outlet />
            }
          </PageContent>

          <PageFooter />
        </Layout>
      </Layout>
    );
  }
};

export default RootLayout;

Home.js

const HomePage = () => {
  const data = useLoaderData();

  console.log(data);

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

export default HomePage;

应用程序加载器.js

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

  let data = {};

  try {
    const response = await axios.get(appsEndPoint(), {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `token ${token}`
      },
      timeout: 30000
    });

    data = response.data;

    return data;
  } catch (error) {
    if (isAxiosError(error)) {
      console.log(error);
      toast.error(error.message);
      return null;
    }
  }
};

export default getApplications;

我最近在课程的帮助下创建了完全相同的登录名,它运行良好,在 RootLayout 显示加载微调器的同时呈现,加载器完成获取后,它会呈现带有数据的出口,正如我们预期的那样。但出于某种原因,在我的应用程序上,它只是在数据出现之前什么都不显示,然后将所有内容吐到屏幕上。

帖子版权声明 1、本帖标题:React Router 6.15.0 在加载程序获取数据时根本不渲染任何内容
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Harish raj在本站《reactjs》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 之前 调用 。换句话说,加载器完成并返回获取的数据, 然后 获取数据时显示加载指示。查看 延迟 数据 指南 .

    以下是执行此操作的代码重构示例:

    import { defer } from "react-router-dom";
    
    const getApplications = async () => {
      const token = localStorage.getItem( 'token' );
    
      try {
        const response = await axios.get(appsEndPoint(), {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `token ${ token }`
          },
          timeout: 30000
        });
    
        return response.data;
      } catch(error) {
        if (isAxiosError(error)) {
          console.log(error);
          toast.error(error.message);
        }
        throw error;
      }
    };
    
    const getApplicationsDeferred = () => {
      return defer({
        applications: getApplications(),
      });
    };
    
    export default getApplicationsDeferred;
    
    import React from 'react';
    import { Await, useLoaderData } from "react-router-dom";
    
    const HomePage = () => {
      const data = useLoaderData();
    
      return (
        <Suspense fallback={<LoadingSpinner />}>
          <Await
            resolve={data.applications}
            errorElement={<p>Error loading applications.</p>}
          >
            {(applications) => {
              console.log(applications);
    
              return (
                <>
                  ...
                  <PageHeader pageTitle='Αιτήσεις' hasBack={ false } />
                  ...
                </>
              )
            }}
          </Await>
        </Suspense>
      );
    };
    
    export default HomePage;
    

    您现在可能不需要根布局中的“加载”UI,只需无条件渲染, Outlet 以便嵌套路线立即可用/可访问。

    <Layout>
      <Navbar />
    
      <Layout>
        <PageContent>
          <Outlet />
        </PageContent>
    
        <PageFooter />
      </Layout>
    </Layout>
    

    这是一个正在运行的演示,它为了演示目的获取假的 JSON 数据,但异步数据/加载流程是相同的。

    Edit exciting-platform-txq5q6

  • 嗨!感谢您付出的时间和精力。我确实了解 defer、Await 和 Suspense 的工作原理,我正准备为我的页面实现相同的逻辑。但让我恼火的是,在我开始我的项目的几天前,我观看了一门 Udemy 课程,该课程遵循的逻辑与我在问题中描述的逻辑完全相同,并且它按预期工作。它加载了 RootLayout,并在 Outlet 的位置加载了一个加载微调器,直到 API 中的数据可用。老师使用的是 React Router 16.12。我尝试使用相同的版本,但没有结果。

返回
作者最近主题: