NextJS:如何使用加载组件而不是 nprogress?

IT技术 javascript node.js reactjs next.js
2021-05-06 19:39:13

是否可以<Loading />在 NextJS 中使用组件而不是 nprogress?我认为您需要pageProps从路由器事件中访问一些高级props,以便您可以切换加载状态,然后有条件地输出加载组件,但我没有看到这样做的方法...

例如,

Router.events.on("routeChangeStart", (url, pageProps) => {
  pageProps.loading = true;
});

并在渲染中

const { Component, pageProps } = this.props;

return pageProps.loading ? <Loading /> : <Page />;

但当然,routeChangeStart不会传入 pageProps。

2个回答

是的,可以使用另一个组件而不是 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.log('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
}