![](/img/trans.png)
[英]How to have a loading screen until all my components are mounted in React
[英]Global loading screen for all components
我正在使用此組件的加載屏幕,同時使用 fetch。
如果我在每個組件中使用fetch()方法,我將必須執行與示例相同的加載邏輯,或者是否有更快更簡單的方法來顯示加載屏幕並在加載所有組件和頁面時將其刪除。
我是 next.js 的新手,我正在使用帶有 express 的 API 將所有數據加載到 next.js 網站。
'use client';
import HeaderStyle from './Header.module.scss';
import { LoadingScreen } from '../LoadingScreen/LoadingScreen';
import Link from 'next/link';
import { usePathname } from "next/navigation";
import { useState, useEffect, createRef} from 'react';
import { UrlObject } from 'url';
function Header(): JSX.Element {
const [data, setData] = useState(null)
const [isLoading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
fetch('http://localhost:5000/getNavegation')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
},
[])
if (isLoading) return <LoadingScreen />;
if (!data) return <header></header>;
return (
<header id={HeaderStyle.header}>
<div className={HeaderStyle.logo}>
<Link href="/" className={HeaderStyle.logoname}>Pedro Alves</Link>
</div>
<div ref={menu} className={HeaderStyle.menu}>
{
data.map((link: { url: string | UrlObject; name: string}, index: number) => (
<Link key={index} className={HeaderStyle.link} href={link.url}>{link.name}</Link>
))}
</div>
<div className={HeaderStyle.toggle_menumobile}>
<span ref={toggle_menumobile} className="icon-base menu-icon"></span>
</div>
</header>
)
}
export default Header;
由於您正在使用外部 API 並在客戶端使用 react 來管理加載 state,因此很難以“Next.js”的方式進行。 如果您想以“Next.js”方式執行此操作,則需要在 next.js 服務器上執行 API 調用,使用 getServerSideProps、HTTP 攔截器或您喜歡的任何方法。 但是,這似乎不像你在這里嘗試做的那樣,為此使用兩個不同的 api 可以被認為是一種反模式。 因此,我們將以反應方式進行。
可以創建一個 LoadingScreen 提供程序,它會刪除您每次要顯示加載屏幕時遇到的重復代碼。 您使用“useLoadingScreen”掛鈎並使用“setLoading”方法而不是之前使用的“isLoading”變量。 我將為此使用 React usecontext,因為它是一個通用的解決方案。 但是,如果您使用全局 state 管理庫,例如 redux、react-query、jotai 或 swt,請隨意使用您各自的庫來實現它。
LoadingProvider.tsx
import React, { createContext, useContext, useState } from 'react'
import LoadingScreen from '...../LoadingScreen/LoadingScreen'';
type LoadingScreenProps = {
loading: boolean;
setLoading: (loading: boolean) => void
}
export const LoadingScreenContext = createContext<LoadingScreenProps>({
loading: false,
setLoading: () => null,
})
export const useLoadingScreen = () => useContext(LoadingScreenContext)
export const LoadingScreenProvider = ({ children }: { children: React.ReactNode }) => {
const [loading, setLoading] = useState<boolean>(false)
if (loading) return <LoadingScreen />
return (
<LoadingScreenContext.Provider value={{ loading, setLoading }}>
{children}
</LoadingScreenContext.Provider>
)
}
確保通過將主要組件包裝在您的提供商中來相應地更新您的“App.tsx”文件
<LoadingScreenProvider>
<Component {...pageProps} />
</LoadingScreenProvider>
更新的用例
'use client';
import HeaderStyle from './Header.module.scss';
import { LoadingScreen } from '../LoadingScreen/LoadingScreen';
import Link from 'next/link';
import { usePathname } from "next/navigation";
import { useState, useEffect, createRef} from 'react';
import { UrlObject } from 'url';
import { useLoadingScreen } from '....../LoadingProvider.tsx'
function Header(): JSX.Element {
const [data, setData] = useState(null)
const { setLoading } = useLoadingScreen;
useEffect(() => {
setLoading(true)
fetch('http://localhost:5000/getNavegation')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
},
[])
if (!data) return <header></header>;
return (
<header id={HeaderStyle.header}>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.