gpt4 book ai didi

reactjs - 延迟加载的 React 路由器路由仍然加载

转载 作者:行者123 更新时间:2023-12-03 13:53:42 26 4
gpt4 key购买 nike

我一直在尝试使用 React.lazy 和 Suspense 在 React 中延迟加载路由。但是,无论当前路线如何,某些组件都会加载,确切地说是:Feed、Profile 和 Settings。
请注意,我实际上并不想延迟加载像 MenuAppBar 和 SnackAlert 这样的组件,但是如果我正常导入它们并删除它们的 Suspense,那么直接进行代码拆分甚至都不起作用,并且所有内容都会加载,整个应用程序只是一个 block 。

import {createMuiTheme, MuiThemeProvider} from "@material-ui/core";
import {yellow} from "@material-ui/core/colors";
import CssBaseline from "@material-ui/core/CssBaseline";
import axios from "axios";
import React, {lazy, Suspense, useEffect, useState} from "react";
import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
import "./css/feed.css";
import "./css/style.css";

const Feed = lazy(() => import("./routes/Feed"));
const Profile = lazy(() => import("./routes/Profile"));
const Home = lazy(() => import("./routes/Home"));
const Settings = lazy(() => import("./routes/Settings"));
const NotFound = lazy(() => import("./routes/NotFound"));
const MenuAppBar = lazy(() => import("./components/MenuAppBar"));
const SnackAlert = lazy(() => import("./components/SnackAlert"));

const App: React.FC = () => {
const [isLogged, setIsLogged] = useState(localStorage.getItem("token") ? true : false);

const [user, setUser] = useState<User>(
isLogged ? JSON.parse(localStorage.getItem("userInfo") as string) : {admin: false}
);
const [openError, setOpenError] = useState<boolean>(false);
const [errorMsg, setErrorMsg] = useState<string>("");
const [severity, setSeverity] = useState<Severity>(undefined);
const [pwa, setPwa] = useState<any>(null);
const [showBtn, setShowBtn] = useState<boolean>(false);
const [isLight, setIsLight] = useState<boolean>(
(JSON.parse(localStorage.getItem("theme") as string) as boolean) ? true : false
);

const theme: customTheme = {
darkTheme: {
palette: {
type: "dark",
primary: {
main: yellow[600]
}
}
},
lightTheme: {
palette: {
type: "light",
primary: {
main: yellow[700]
}
}
}
};

window.addEventListener("beforeinstallprompt", (event) => {
event.preventDefault();
setPwa(event);
setShowBtn(true);
});

window.addEventListener("appinstalled", (e) => {
setShowBtn(false);
setErrorMsg("App installed!");
setSeverity("success");
setOpenError(true);
});

const handleClick = () => {
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
setErrorMsg(`Please, open the share menu and select "Add to Home Screen"`);
setSeverity("info");
setOpenError(true);
} else {
if (pwa) {
pwa.prompt();
pwa.userChoice.then((choiceResult: {outcome: "accepted" | "refused"}) => {
if (choiceResult.outcome === "accepted") {
setErrorMsg("App downloading in the background..");
setSeverity("info");
setOpenError(true);
}
setPwa(null);
});
}
}
};

useEffect(() => {
const token: string | null = localStorage.getItem("token");
let userInfo: User = JSON.parse(localStorage.getItem("userInfo") as string);
if (userInfo && token && !userInfo.admin) {
setUser(userInfo);
setIsLogged(true);
}
if (isLogged) {
axios
.get("/api/auth/user", {
headers: {
"x-auth-token": `${token}`
}
})
.then((res) => {
if (!userInfo || !token) {
setUser(res.data as User);
}
localStorage.setItem(`userInfo`, JSON.stringify(res.data as User));
setIsLogged(true);
})
.catch((err) => {
if (err) {
setIsLogged(false);
}
});
} else {
localStorage.removeItem("token");
localStorage.removeItem("userInfo");
}
}, [isLogged]);

return (
<MuiThemeProvider theme={isLight ? createMuiTheme(theme.lightTheme) : createMuiTheme(theme.darkTheme)}>
<CssBaseline />
<Router>
<Suspense fallback={<div></div>}>
<Route
path="/"
render={() => (
<>
<MenuAppBar
isLogged={isLogged}
setIsLogged={setIsLogged}
user={user}
setUser={setUser}
isLight={isLight}
setIsLight={setIsLight}
/>
<SnackAlert severity={severity} errorMsg={errorMsg} setOpenError={setOpenError} openError={openError} />
</>
)}
/>
</Suspense>
<Suspense fallback={<div></div>}>
<Switch>
<Route exact path="/" render={() => <Home />} />

<Route exact path="/profile/:id" render={() => <Profile />} />

<Route exact path="/feed" render={() => <Feed isLogged={isLogged} user={user} />} />

<Route
exact
path="/settings"
render={() => (
<Settings isLight={isLight} setIsLight={setIsLight} handleClick={handleClick} showBtn={showBtn} />
)}
/>
<Route render={() => <NotFound />} />
</Switch>
</Suspense>
</Router>
</MuiThemeProvider>
);
};

export default App;

最佳答案

您正在包装整个 Switch在一个 Suspense ,因此所有组件将同时延迟加载。您可能只希望在第一次呈现特定路线时获取/加载每个。

<Switch>
<Route
exact
path="/"
render={props => (
<Suspense fallback={<div>Loading...<div>}>
<Home {...props} />
</Suspense>
)}
/>
<Route
exact
path="/profile/:id"
render={props => (
<Suspense fallback={<div>Loading...<div>}>
<Profile {...props} />
</Suspense>
)}
/>
<Route
exact
path="/feed"
render={() => (
<Suspense fallback={<div>Loading...<div>}>
<Feed isLogged={isLogged} user={user} {...props} />
</Suspense>
)}
/>
<Route
exact
path="/settings"
render={() => (
<Suspense fallback={<div>Loading...<div>}>
<Settings
isLight={isLight}
setIsLight={setIsLight}
handleClick={handleClick}
showBtn={showBtn}
{...props}
/>
</Suspense>
)}
/>
<Route
render={() => <NotFound />}
/>
</Switch>
这里有很多重复,所以把悬念分解成一个 HOC 是很实际的。
const withSuspense = (WrappedComponent, fallback) => props => (
<Suspense fallback={fallback}>
<WrappedComponent {...props} />
</Suspense>
);
您可以装饰每个透视默认导出,即
export default withSuspense(Home, <div>Loading...<div>);
应用程序.js
...
<Switch>
<Route exact path="/" render={props => <Home {...props} />} />
或在您的应用中装饰它们
const HomeWithSuspense = withSuspense(Home, <div>Loading...<div>);

...

<Switch>
<Route
exact
path="/"
render={props => <HomeWithSuspense {...props} />}
/>
...
</Switch>

关于reactjs - 延迟加载的 React 路由器路由仍然加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60250800/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com