[copy airbnb] 8. 个人列表视图

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 提供了基于文件系统的路由机制,允许你定义动态路由,并在页面组件的 getServerSidePropsgetStaticProps 中获取 URL 参数。

在下面代码中,listingPage 是一个异步函数,用于渲染某个特定列表项的页面。虽然代码本身没有使用 getServerSidePropsgetStaticProps,但它展示了如何获取 URL 参数并进行相应的操作。

获取 URL 参数的方式

  1. 动态路由:在 Next.js 中,你可以通过文件名中的方括号来定义动态路由。例如,pages/listing/[listingId].tsx 定义了一个动态路由,其中 listingId 是一个变量。
  2. 函数参数: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>

解释

  1. 动态路由:文件名 [listingId].tsx 告诉 Next.js 这是一个动态路由,listingId 是一个可变的部分。
  2. getServerSideProps:这个函数在服务器端运行,在请求到达页面之前获取数据。它接受一个 context 参数,包含 params,其中包含 URL 参数。
  3. 页面组件:在 ListingPage 组件中,使用 props 获取服务器端传递的数据。

通过这种方式,你可以在 Next.js 中轻松地获取 URL 参数并在服务器端进行数据获取和处理。

ps:也可以写在app下面,也能达到类似的效果:src/app/listings/[listingId]/page.tsx

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部