typescript 所有组件的全局加载屏幕

wd2eg0qa  于 2022-11-26  发布在  TypeScript
关注(0)|答案(1)|浏览(130)

我在使用fetch时,使用了此组件的加载屏幕。
如果我在每个组件中使用 fetch() 方法,我将不得不执行与示例相同的加载逻辑,或者是否有更快、更简单的方法来显示加载屏幕,并在加载所有组件和页面时删除它。
我是新来的下一个js,我正在使用一个API与表达加载所有数据到下一个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;
h5qlskok

h5qlskok1#

“Next.js”方式

由于您使用外部API并在客户端使用react来管理加载状态,因此很难以“Next.js”的方式完成。如果您希望以“Next.js”的方式完成,则需要在next.js服务器上执行API调用,可以使用getServerSideProps、HTTP拦截器或任何您喜欢的方法。但是,这看起来不像你在这里要做的,使用两个不同的api可以被认为是一个反模式。所以,我们将用react的方式来做。

“React”方式

您可以创建一个LoadingScreen提供程序,它可以删除每次显示加载屏幕时遇到的重复代码。您可以使用'useLoadingScreen'挂钩和'setLoading'方法,而不是之前使用的'isLoading'变量。我将使用React usecontext来实现这一点,因为它是一个通用的解决方案。但是,如果您使用的是全局状态管理库(如redux),react-query、jotai或swt可以用各自库来实现它。

正在加载提供程序.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>
    )
}

请确保通过使用提供程序 Package 主组件来相应地更新“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}>

相关问题