NextJS:如何使用加载组件代替nprogress?

时间:2019-01-22 16:50:37

标签: javascript node.js reactjs next.js

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

例如

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

和渲染中

const { Component, pageProps } = this.props;

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

但是,当然routeChangeStart不会传入pageProps。

2 个答案:

答案 0 :(得分:1)

使用下面的钩子检查路由器的加载状态:

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
}

答案 1 :(得分:0)

是的,可以使用另一个组件代替nProgress来处理加载。我有一个类似的问题,发现下面的解决方案可以为我解决。

./pages/_app.js中执行所有这些操作很有意义,因为according to the documentation可以帮助持久保留页面之间的布局和状态。您可以在生命周期方法componentDidMount上启动Router事件。重要的是要注意,_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;