我正在服务器组件中加载客户端组件,但尝试显示后备加载程序,直到通过 API 在客户端中获取数据。
我有以下服务器组件,其中包含客户端组件
import { LoggedInUserModel } from "@/models/common/logged-in-user-model";
import { Suspense } from "react";
import dynamic from "next/dynamic";
import ProfileLoading from "./loading22";
const UserProfile = dynamic(() => import("./components/userProfile"), {
ssr: false,
});
const MyProfile = async () => {
const user: LoggedInUserModel = await userService.getUser();
return (
<>
<div className="row mt-3 justify-content-md-center">
<div className="col-12 col-md-8">
<nav
aria-label="breadcrumb"
className="p-3 bg-white rounded-3 shadow-sm mb-4"
>
<ol className="breadcrumb mb-0">
<li className="breadcrumb-item">
<a className="text-decoration-none">
<i className="fa-solid fa-user"></i> My Profile
</a>
</li>
</ol>
</nav>
</div>
<UserProfile user={user} />
</div>
</>
);
};
export default MyProfile;
我的客户端组件用户配置文件是
"use client";
import { UserProfileModel } from "./../../../../models/User/user-profile-model";
import { Suspense, lazy, use, useEffect, useState } from "react";
import fetchClientData from "@/lib/fetchClientData";
import { LoggedInUserModel } from "@/models/common/logged-in-user-model";
import ProfileLoading from "../loading22";
import React from "react";
const AbcProfile = lazy(() => import("./abcprofile"));
type UserProfileProps = {
user: LoggedInUserModel;
};
const UserProfile = ({ user }: UserProfileProps) => {
return (
<Suspense fallback={<h2>Data loading...........</h2>}>
<AbcProfile />
</Suspense>
);
};
export default UserProfile;
AbcProfile 组件:
import { use, useEffect, useState } from "react";
const AbcProfile = () => {
use(
fetch(`/api/user/profile/6490986e0d0ce1756d2b491b`).then((res) =>
res.json()
)
);
return <h2>Data loaded</h2>;
};
export default AbcProfile;
当我运行代码时,它确实显示了后备加载程序,但 API 被调用 4 次以从服务器获取数据。为什么?如何正确 在客户端组件中使用 nextjs 的 Suspense 吗?
页面SSR和组件CSR的混合模式似乎有一些局限性。例如,Suspense 组件不会回退,因为它认为它已经渲染了客户端组件。但客户端组件可能正在调用 API 来加载数据。对于这种混合方法,我将使用 useEffect 挂钩来调用 API,然后显式加载回退。当页面和组件使用完整的 SSR 或 CSR 时,Suspense 会按预期工作。
const UserProfile = ({ user }: UserProfileProps) => {
const [profile, setProfile] = useState(null);
useEffect(() => {
const fetchData = async () => {
const data = fetch(`/api/user/profile/6490986e0d0ce1756d2b491b`).then((res) =>
res.json()
)
setProfile(data);
};
fetchData();
}, []); // Re-fetch query changes)
if (!profile){
return (<h2>Data loading...........</h2>)
}
return (
<h1>{profile.name}</h1>
);
};