简体   繁体   English

如何使用 NextJS 只使用一次动态导入

[英]How to use dynamic import one time only with NextJS

I am building an App with NextJS, I'd like to render loading icon while fetching data or loading some pages.我正在使用 NextJS 构建一个应用程序,我想在获取数据或加载某些页面时呈现加载图标。 Currently I have to insert Loading component into each compomnent, for example if you have HomePage, you have to import Loading to HomePage, then if you have ProductList, you will also have to import Loading into ProductList, .... While I think it's better if I can import Loading one time only and apply for whole app, like React Lazy + suspend.目前我必须将 Loading 组件插入到每个组件中,例如,如果您有 HomePage,则必须将 Loading 导入 HomePage,然后如果您有 ProductList,您还必须将 Loading 导入 ProductList,....虽然我认为是如果我可以只导入一次加载并申请整个应用程序,比如 React Lazy + 暂停,那就更好了。 The docs of NextJS only guides you how to do with each Component only. NextJS 的文档仅指导您如何处理每个组件。 I have tried React Lazy + Suspend but this didn't work as well.我已经尝试过 React Lazy + Suspend 但这并不奏效。 Could you please advise should I put dynamic import.您能否建议我是否应该进行动态导入。

Appreciate any advice.感谢任何建议。

file pages/_app.js:文件页面/_app.js:

function MyApp({ Component, pageProps }) {
    return (
        <>
            <Head>
                <meta charSet="utf-8" />
                <meta name="viewport" content="width=device-width, initial-scale=1" />
                <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossOrigin="anonymous" />
                <title>Hello, world!</title>
                <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossOrigin="anonymous"></script>
                <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossOrigin="anonymous"></script>
                <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossOrigin="anonymous"></script>
            </Head>

            <Header />

            <main className="pt-3">
                <Component {...pageProps} />
            </main> 

            <Footer />
        </>
    )
}

export default MyApp;

If you want to add global loading whenever the data is fetching, you can try to put the loading state in the redux.如果要在数据获取时添加全局加载,可以尝试将loading state放在 redux 中。 A way to accomplish it might be like this.实现它的方法可能是这样的。

_app.js _app.js

import { useSelector, useDispatch } from 'redux';

function MyApp({ Component, pageProps }) {
  const isLoading = useSelector((state) => state.isLoading);
  
  const dispatch = useDispatch();
  
  useEffect(() => {
    Router.events.on('routeChangeComplete', () => {
      // when route has been changed complete, dispatch an action which would make the loading state to be true
      dispatch({ type: 'CHANGE_LOADING_STATE', payload: true });
  }, [])

  return (
    <WithLoadingComponent>
       <Component {...pageProps} />
    </WithLoadingComponent>
  );
}

WithLoadingComponent WithLoadingComponent

import { useSelector } from 'redux';
import Router from 'next/router';

function WithLoadingComponent(props) {
  const isLoading = useSelector((state) => state.isLoading);
  
  return (
    <>
      {isLoading && <GlobalLoadingComponent />}
      <div className={isLoading ? 'loading' : ''}>{props.children}</div>
      <style jsx>{`
        .loading {
          visibility: hidden;
        }
      `}</style>
    </>
  );
}

PageComponent页面组件

import { useDispatch } from 'redux';

function PageComponent(props) {
  const dispatch = useDispatch();

  useEffect(() => {
    // Call api to fetch data
    (async () => {
      try {
        const data = await fetch('https://www.xxyyzz.com/api');
        console.log(data);
        dispatch({ type: 'CHANGE_LOADING_STATE', payload: false });
      } catch (error) {
        dispatch({ type: 'CHANGE_LOADING_STATE', payload: false });
      }
    })();
  }, []);

  return <div>Page component</div>;
}

However, I think to show the global loading state in every page doesn't seems reasonable.但是,我认为在每个页面中显示全局加载 state 似乎并不合理。 Because most of the time, it just call the api and then render a portion of the part on the screen (not the entire screen).因为大多数时候,它只是调用 api 然后在屏幕上渲染一部分部分(而不是整个屏幕)。 The better way would be show the loading icon only on a small part of the screen which would show the response data later from the api.更好的方法是仅在屏幕的一小部分显示加载图标,稍后将显示来自 api 的响应数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM