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



我是nextjs的新手,使用nextjs v9.3next-redux-wrapper v5@material-ui/core v4.2custom express server

我试图在Nextjs应用程序中更改路由时实现加载屏幕,因此我使用帧器运动在页面之间进行转换,工作正常,但现在更改路由时如何使用加载组件

我目前的实现如下:

_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中,当我使用帧移动时

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;

我就是这样做的。在_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} />
}
...
)
}

这可能会有所帮助,您可以将此组件放置在布局组件中并用它包装_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 />设计为在调用时接管设备的整个视框。

最新更新