1、交叉类型
interface ListingClientProps{
reservations:Reservation[];
listing:SafeListing & {
user:SafeUser
},
currentUser:SafeUser|null
}
在这个 TypeScript 接口定义中,listing: SafeListing & { user: SafeUser }
使用了 TypeScript 的“交叉类型”(Intersection Types)语法。交叉类型是将多个类型合并为一个类型的方式,这意味着你可以将现有的多个类型叠加在一起,得到一个包含所有类型属性的单一类型。这在你想要组合多个类型的属性到一个类型里时非常有用。
具体来说,在 ListingClientProps
接口中:
SafeListing & { user: SafeUser }
这部分表示listing
属性是一个合并类型,它结合了SafeListing
类型的所有属性和一个额外的user
属性,其中user
属性的类型是SafeUser
。
这意味着:
listing
属性将包括SafeListing
类型中的所有属性。- 此外,
listing
还会有一个名为user
的属性,其类型为SafeUser
。
简单地说,这段代码定义了 ListingClientProps
必须有一个名为 listing
的属性,这个属性不仅包含 SafeListing
类型的所有属性,还包含一个额外的 user
属性,且 user
的类型是 SafeUser
。
交叉类型提供了一种灵活的方式来组合现有类型,使得 TypeScript 的类型系统既强大又灵活。
2、联合类型
在 Next.js 中,你可以通过动态路由参数(URL 参数)来获取数据。这是因为 Next.js 提供了基于文件系统的路由机制,允许你定义动态路由,并在页面组件的 getServerSideProps
或 getStaticProps
中获取 URL 参数。
在下面代码中,listingPage
是一个异步函数,用于渲染某个特定列表项的页面。虽然代码本身没有使用 getServerSideProps
或 getStaticProps
,但它展示了如何获取 URL 参数并进行相应的操作。
获取 URL 参数的方式
- 动态路由:在 Next.js 中,你可以通过文件名中的方括号来定义动态路由。例如,
pages/listing/[listingId].tsx
定义了一个动态路由,其中listingId
是一个变量。 - 函数参数:Next.js 会自动将 URL 参数传递给页面组件。你可以在函数参数中接收这些参数,如你的代码所示。
具体实现
假设你有一个动态路由 pages/listing/[listingId].tsx
:
import getCurrentUser from "@/app/actions/getCurrentUser";
import getListingById from "@/app/actions/getListingById";
import ClientOnly from "@/app/components/ClientOnly";
import EmptyState from "@/app/components/EmptyState";
import ListingClient from "./listingClient";
interface IParams {
listingId?: string;
}
const ListingPage = async ({ params }: { params: IParams }) => {
const listing = await getListingById(params.listingId);
const currentUser = await getCurrentUser();
if (!listing) {
return (
<ClientOnly>
<EmptyState />
</ClientOnly>
);
}
return (
<ClientOnly>
<ListingClient listing={listing} currentUser={currentUser} />
</ClientOnly>
);
};
export default ListingPage;
</code>
使用 getServerSideProps
为了在服务器端获取 URL 参数并传递给页面组件,你可以使用 getServerSideProps
:
import getCurrentUser from "@/app/actions/getCurrentUser";
import getListingById from "@/app/actions/getListingById";
import ClientOnly from "@/app/components/ClientOnly";
import EmptyState from "@/app/components/EmptyState";
import ListingClient from "./listingClient";
interface IParams {
listingId?: string;
}
export async function getServerSideProps(context: { params: IParams }) {
const { params } = context;
const listing = await getListingById(params.listingId);
const currentUser = await getCurrentUser();
return {
props: {
listing,
currentUser,
},
};
}
const ListingPage = ({ listing, currentUser }) => {
if (!listing) {
return (
<ClientOnly>
<EmptyState />
</ClientOnly>
);
}
return (
<ClientOnly>
<ListingClient listing={listing} currentUser={currentUser} />
</ClientOnly>
);
};
export default ListingPage;
</code>
解释
- 动态路由:文件名
[listingId].tsx
告诉 Next.js 这是一个动态路由,listingId
是一个可变的部分。 getServerSideProps
:这个函数在服务器端运行,在请求到达页面之前获取数据。它接受一个context
参数,包含params
,其中包含 URL 参数。- 页面组件:在
ListingPage
组件中,使用props
获取服务器端传递的数据。
通过这种方式,你可以在 Next.js 中轻松地获取 URL 参数并在服务器端进行数据获取和处理。
ps:也可以写在app下面,也能达到类似的效果:src/app/listings/[listingId]/page.tsx