nextjs getServerSideProps 显示加载

Posted

技术标签:

【中文标题】nextjs getServerSideProps 显示加载【英文标题】:nextjs getServerSideProps show loading 【发布时间】:2020-06-30 11:28:39 【问题描述】:

我在pages/post/index.js 中使用getServerSideProps:

import React from "react";
import Layout from "../../components/Layout";

function Post( post ) 
  console.log("in render", post);
  return (
    <Layout title=post.name>
      <pre>JSON.stringify(post, undefined, 2)</pre>
    </Layout>
  );


export async function getServerSideProps( query ) 
  return fetch(
    `$process.env.API_URL/api/post?id=$query.id`
  )
    .then(result => result.json())
    .then(post => ( props:  post  ));


export default Post;

当我直接加载 /post/2 时,它按预期工作,但是当我通过单击链接从 /posts 转到 /post/2 时:

<Link
  as=`/post/$post.id`
  href=`/post?id=$post.id`
>

在 2 秒 (the api delay) 内似乎没有任何反应,然后显示内容。我可以在网络选项卡中看到_next/data/development/post/9.json 正在由fetchNextData 加载。

当我使用 next/Link 从一条路线移动到另一条路线时,我想显示一个加载微调器,但我在 getServerSideProps 上找不到任何允许我这样做的文档。

当我直接转到/post/:id 时,我希望在服务器端获取数据并获得一个完全呈现的页面(有效),但是当我移动到另一条路线时,应该从客户端获取数据(有效) .然而;我想要一个加载指示器,并且在数据请求期间不让 UI 冻结。

【问题讨论】:

【参考方案1】:

您可以在_app.js 中使用nprogress

import NProgress from 'nprogress';
import "nprogress/nprogress.css";
import Router from 'next/router';

NProgress.configure(
  minimum: 0.3,
  easing: 'ease',
  speed: 800,
  showSpinner: false,
);

Router.events.on('routeChangeStart', () => NProgress.start());
Router.events.on('routeChangeComplete', () => NProgress.done());
Router.events.on('routeChangeError', () => NProgress.done());

或动态导入到_app.js 以减小包大小

ProgessBar.js

import Router from 'next/router';
import NProgress from 'nprogress';

NProgress.configure(
    minimum: 0.3,
    easing: 'ease',
    speed: 500,
    showSpinner: false,
);

Router.events.on('routeChangeStart', () => NProgress.start());
Router.events.on('routeChangeComplete', () => NProgress.done());
Router.events.on('routeChangeError', () => NProgress.done());

export default function () 
    return null;

_app.js

import "nprogress/nprogress.css";
import dynamic from 'next/dynamic';
const ProgressBar = dynamic(() => import('components/atoms/ProgressBar'),  s-s-r: false );

const App = () => 
   ...
   return <>
       ...
       <ProgressBar />
   </>

【讨论】:

谢谢,我会试试this example。 我最终选择了using hooks 不要忘记导入css,否则它不会显示。 import "nprogress/nprogress.css";【参考方案2】:
**Here is how I did it in NextJs with Material UI and nprogress**

import '../styles/globals.css';
import  useEffect, useState  from 'react';
import Router from 'next/router';
import NProgress from 'nprogress';

import  useStyles  from '../src/utils';
import  CircularProgress  from '@material-ui/core';

NProgress.configure( showSpinner: false );

function MyApp(
  Component,
  pageProps
 
) 
  const classes = useStyles();
  const [loading, setLoading] = useState(false);

  useEffect(() => 
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles) jssStyles.parentElement.removeChild(jssStyles);

    const start = () => 
      console.log('start');
      NProgress.start();
      setLoading(true);
    ;
    const end = () => 
      console.log('findished');
      NProgress.done();
      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 ? (
          <div className=classes.centered>
            <CircularProgress size=25 color='primary' />
          </div>
        ) : (
        <Component ...pageProps />
       )
    </>
  );


export default MyApp;

结果:

【讨论】:

【参考方案3】:

这是一个使用钩子的example。

pages/_app.js

import Router from "next/router";

export default function App( Component, pageProps ) 
  const [loading, setLoading] = React.useState(false);
  React.useEffect(() => 
    const start = () => 
      console.log("start");
      setLoading(true);
    ;
    const end = () => 
      console.log("findished");
      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 ? (
        <h1>Loading...</h1>
      ) : (
        <Component ...pageProps />
      )
    </>
  );

【讨论】:

感谢您提供出色的解决方案 它是否适用于使用getServerSideProps 的 s-s-r?它对我不起作用。 @ka8725 是的,它适用于 getServerSideProps

以上是关于nextjs getServerSideProps 显示加载的主要内容,如果未能解决你的问题,请参考以下文章

为啥 NextJS 中的 ApolloGraphQL 示例使用 getStaticProps 而不是 getServerSideProps

在 NEXTJS 的 getServerSideProps() 中获取一些 html 表单数据(或对象)

如何将道具从组件传递到 NextJS 中的 getServerSideProps()?

nextjs getServerSideProps 显示加载

无法导出带有 getServerSideProps 的 nextjs 页面

NextJS 是不是包含仅在包中的 getServerSideProps 中引用的库?