Я использую экран загрузки для этого компонента при использовании 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;
Из-за того, что вы используете внешний API и используете реакцию на стороне клиента для управления состоянием загрузки, будет сложно сделать это способом «Next.js». Если вы хотите сделать это способом «Next.js», вызовы API необходимо будет выполнять на сервере next.js либо с помощью getServerSideProps, либо с помощью перехватчика HTTP, либо с помощью любого другого метода. Но это не похоже на то, что вы пытаетесь сделать здесь, и использование двух разных API для этого можно считать антипаттерном. Поэтому вместо этого мы сделаем это способом реагирования.
Можно создать поставщика LoadingScreen, который удаляет повторяющийся код, с которым вы сталкиваетесь каждый раз, когда хотите показать экран загрузки. Вы используете хук «useLoadingScreen» и используете метод «setLoading» вместо переменной «isLoading», которую вы использовали ранее. Я буду использовать для этого React usecontext, так как это универсальное решение. Но если вы используете глобальную библиотеку управления состоянием, такую как 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}>