Можно ли использовать компонент <Loading /> в NextJS вместо nprogress? Я думаю, вам понадобится доступ к некоторым реквизитам высокого уровня, таким как pageProps, из событий маршрутизатора, чтобы вы могли переключать состояние загрузки, а затем условно выводить загрузочный компонент, но я не вижу способа сделать это...
Например,
Router.events.on("routeChangeStart", (url, pageProps) => {
pageProps.loading = true;
});
и в рендере
const { Component, pageProps } = this.props;
return pageProps.loading ? <Loading /> : <Page />;
Но, конечно же, routeChangeStart не проходит в pageProps.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Да, можно использовать другой компонент для обработки загрузки вместо nProgress. У меня был аналогичный вопрос, и я нашел решение ниже, которое работает для меня.
Все это имеет смысл делать в ./pages/_app.js, потому что согласно документации может помочь с сохранением макета и состояния между страницами. Вы можете инициировать события маршрутизатора в методе жизненного цикла componentDidMount. Важно отметить, что _app.js монтируется только один раз, но инициация событий маршрутизатора здесь все равно будет работать. Это позволит вам установить состояние.
Ниже приведен пример того, как все это сочетается:
import React, { Fragment } from 'react';
import App from 'next/app';
import Head from 'next/head';
import Router from 'next/router';
class MyApp extends App {
state = { isLoading: false }
componentDidMount() {
// Logging to prove _app.js only mounts once,
// but initializing router events here will also accomplishes
// goal of setting state on route change
console.info('MOUNT');
Router.events.on('routeChangeStart', () => {
this.setState({ isLoading: true });
});
Router.events.on('routeChangeComplete', () => {
this.setState({ isLoading: false });
});
Router.events.on('routeChangeError', () => {
this.setState({ isLoading: false });
});
}
render() {
const { Component, pageProps } = this.props;
const { isLoading } = this.state;
return (
<Fragment>
<Head>
<title>My App</title>
<meta name = "viewport" content = "width=device-width, initial-scale=1" />
<meta charSet = "utf-8" />
</Head>
{/* You could also pass isLoading state to Component and handle logic there */}
<Component {...pageProps} />
{isLoading && 'STRING OR LOADING COMPONENT HERE...'}
</Fragment>
);
}
}
MyApp.getInitialProps = async ({ Component, ctx }) => {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
};
export default MyApp;
Используйте хук ниже, чтобы проверить состояние загрузки маршрутизатора:
import Router from 'next/router'
import { useState, useEffect } from 'react'
const useRouterLoading = () => {
const [loading, setLoading] = useState(false)
useEffect(() => {
const start = () => setLoading(true)
const end = () => setLoading(false)
Router.events.on('routeChangeStart', start)
Router.events.on('routeChangeComplete', end)
Router.events.on('routeChangeError', end)
return () => {
Router.events.off('routeChangeStart', start)
Router.events.off('routeChangeComplete', end)
Router.events.off('routeChangeError', end)
}
}, [])
return loading
}
Это действительно хорошее решение @duan. Возможно, его можно расширить, чтобы показать ошибку и статус ошибки? Что-то вроде: gist.github.com/adamduncan/2e5b9c2eafe74fd9fda902a6ea213ba3