如何在Next.js中实现加载屏幕

taor4pac  于 2023-06-05  发布在  其他
关注(0)|答案(2)|浏览(204)

我是nextjs的新手,使用nextjs v9.3next-redux-wrapper v5@material-ui/core v4.2custom express server
我试图在我的Nextjs应用程序中更改路由时实现加载屏幕,所以我使用framer motion进行页面之间的转换,工作正常,但现在如何在更改路由时使用加载组件
我目前的实现如下:

_app.js

import React, { useEffect } from "react";
import { ThemeProvider } from "@material-ui/core/styles";
import { CssBaseline } from "@material-ui/core";
import { theme } from "../lib/theme";
import withRedux from "next-redux-wrapper";
import { Provider } from "react-redux";
import reduxStore from "../store/store";
import { PersistGate } from "redux-persist/integration/react";
import { AnimatePresence } from "framer-motion";
import Navbar from "../components/Navbar";
import Meta from "../components/Meta";

function MyApp(props) {
  useEffect(() => {
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles && jssStyles.parentNode)
      jssStyles.parentNode.removeChild(jssStyles);
  }, []);
  const { Component, pageProps, store, router } = props;
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Provider store={store}>
        <PersistGate persistor={store.__PERSISTOR} loading={null}>
          <Meta/>
          <Navbar {...props} />
          <AnimatePresence exitBeforeEnter>
            <Component {...pageProps} key={router.route}/>
          </AnimatePresence>
        </PersistGate>
      </Provider>
    </ThemeProvider>
  );
}

export default withRedux(reduxStore)(MyApp);

更新

`___-_-_-_-_my solution_-_-_-_-___`

方法1:在next.js v9.3中使用framer-motion时

import React, {
  useEffect,
  useState,
} from "react";
import { ThemeProvider as MaterialThemeProvider } from "@material-ui/core/styles";
import { ThemeProvider as StyledThemeProvider } from "styled-components";
import { CssBaseline } from "@material-ui/core";
import { AnimatePresence, motion } from "framer-motion";
import theme from "../lib/theme";
import Layout from "../components/Layout";
import Loader from "react-loader-spinner";

function MyApp(props) {
  const { Component, pageProps, router } = props;
  // blow useState & useEffect for tracking change route
  const [isRouteChanging, setIsRouteChanging] = useState(false);
  useEffect(() => {
    const routeChangeStartHandler = () => setIsRouteChanging(true);

    const routeChangeEndHandler = () => setIsRouteChanging(false);

    router.events.on("routeChangeStart", routeChangeStartHandler);
    router.events.on("routeChangeComplete", routeChangeEndHandler);
    router.events.on("routeChangeError", routeChangeEndHandler);
    return () => {
      router.events.off("routeChangeStart", routeChangeStartHandler);
      router.events.off("routeChangeComplete", routeChangeEndHandler);
      router.events.off("routeChangeError", routeChangeEndHandler);
    };
  }, []);

  // useEffect config material-ui
  useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles && jssStyles.parentNode)
      jssStyles.parentNode.removeChild(jssStyles);
  }, []);

  return (
    <StyledThemeProvider theme={theme}>
      <MaterialThemeProvider theme={theme}>
        <CssBaseline />
        {/*animation for each page when route changes*/}
        <Layout>
          {isRouteChanging ? (
            <motion.div
              initial={{
                opacity: 0,
                height: "90vh",
                display: "flex",
                justifyContent: "center",
                alignItems: "center",
              }}
              animate={{
                opacity: 1,
              }}
              exit={{
                opacity: 0,
              }}
            >
              <Loader
                type="Grid"
                color={theme.spinnerColor}
                height={80}
                width={80}
              />
            </motion.div>
          ) : (
            <AnimatePresence exitBeforeEnter>
              <Component {...pageProps} key={router.route} />
            </AnimatePresence>
          )}
        </Layout>
      </MaterialThemeProvider>
    </StyledThemeProvider>
  );
}

export default MyApp;

方法2:在next.js v10及更高版本中,我使用了“nprogress”:“^0.2.0”

import React, { useEffect } from "react";
import Router from "next/router";
// Material UI Core
import CssBaseline from "@material-ui/core/CssBaseline";
import { ThemeProvider } from "@material-ui/core/styles";
// Utils
import theme from "Utils/theme";
// NProgress
import NProgress from "nprogress";

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

function MyApp({ Component, pageProps}) {

  // useEffect config material-ui
  useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles && jssStyles.parentNode)
      jssStyles.parentNode.removeChild(jssStyles);
  }, []);

  return (
    <Provider store={store}>
      <ThemeProvider theme={theme}>
              <CssBaseline />
              <Component {...pageProps} />
      </ThemeProvider>
    </Provider>
  );
}

export default MyApp;
ijxebb2r

ijxebb2r1#

我是这样做的。在_app.tsx中:

import { useRouter } from 'next/router';

const MyApp = ({
  MainComponent, 
  pageProps,
}) => {    
const router = useRouter();
    const [pageLoading, setPageLoading] = React.useState<boolean>(false);
    React.useEffect(() => {
        const handleStart = () => { setPageLoading(true); };
        const handleComplete = () => { setPageLoading(false); };
    
        router.events.on('routeChangeStart', handleStart);
        router.events.on('routeChangeComplete', handleComplete);
        router.events.on('routeChangeError', handleComplete);
      }, [router]);

return (
  ...
  { pageLoading 
    ? (<div>Loading</div>)
    : <MainComponent {...pageProps} />
  }
  ...

)

}
hfwmuf9z

hfwmuf9z2#

这可能会有所帮助,您可以将此组件放置在布局组件中并使用它 Package _app.js,或者直接将其导入到_app.js

import React from 'react';
import Router from 'next/router';
import CustomLoadingScreen from './components/CustomLoadingScreen'; // example

Router.onRouteChangeStart = () => {
    console.log('onRouteChangeStart Triggered');
    <CustomLoadingScreen />;

};

Router.onRouteChangeComplete = () => {
    console.log('onRouteChangeComplete Triggered');
    <CustomLoadingScreen />;

};

Router.onRouteChangeError = () => {
    console.log('onRouteChangeError Triggered');
    <CustomLoadingScreen />;

};

您可以设计<CustomLoadingScreen />,使其在被调用时接管设备的整个视图框。

相关问题