type
Post
status
Published
date
Feb 8, 2026
slug
nextjs-shopping-platform-005
summary
tags
Next.js
category
编程学习
icon
password
😀

1. Section Intro

This section is all about adding and removing items from the cart. We'll have a table in the database that represents the cart and the products within it. So we need to create a Prisma schema and model for that.
本章节主要介绍如何从购物车中添加和移除商品。我们将在数据库中创建一个表来表示购物车及其中的商品。因此,我们需要为此创建Prisma模式和模型。
Now since we're going to allow guests to add products to the cart, we need a way to link them to their cart so we're going to write some code in the NextAuth callback to add a 'sessionCartId' that will link the user to their cart in the database.
现在,由于我们要允许访客将商品添加到购物车,我们需要一种方式将他们与购物车关联起来,因此我们将在NextAuth回调中编写一些代码,添加一个'sessionCartId',用于将用户与数据库中的购物车关联起来。
Then we'll be creating the add to cart component for the UI and create an action to add the item to the cart, which means adding it to the database. Then we want to add the functionality to remove items from the cart as well.
然后,我们将为UI创建"添加到购物车"组件,并创建一个操作来将商品添加到购物车,这意味着将其添加到数据库中。之后,我们还想添加从购物车中移除商品的功能。
We need to create actions to add and remove to and from the cart.
我们需要创建用于向购物车添加和移除商品的操作。
We're also going to make our cart按钮 dynamic in that once we add a product, the button will change to show an add and remove quantity selection.
我们还将使我们的购物车按钮具有动态性,一旦添加商品,按钮就会改变,显示添加和移除数量的选择。
We're going to use the useTransition hook to show a loading state while the action is running.
我们将使用useTransition钩子,在操作运行时显示加载状态。

2. Cart Zod Schema & Prisma Model 购物车模式和模型

We are going to prepare our data for the shopping cart. We will create a Zod schema as well as our Prisma schema to prepare the database.
我们将为购物车准备数据。我们将创建Zod模式以及Prisma模式来准备数据库。

Item Schema 商品模式

Let's add the Zod schema for the items in the cart. Open the lib/validator.ts file and add the following schema:
让我们为购物车中的商品添加Zod模式。打开lib/validator.ts文件,添加以下模式:
🗒️
/^\\d+(\\.\\d{2})?$/ 改成 /^\d+(\.\d{2})?$/
This schema will be used to validate the cart items when we get the cart.
当我们获取购物车时,这个模式将用于验证购物车商品。

Cart Schema 购物车模式

Let's add the schema for the cart itself. Open the lib/validator.ts file and add the following schema:
让我们为购物车本身添加模式。打开lib/validator.ts文件,添加以下模式:

Add The Types 添加类型

Let's add a new type. Open the types/index.ts file and add the following types:
让我们添加一个新类型。打开types/index.ts文件,添加以下类型:
Now we can use the CartItem type in our application.
现在我们可以在应用程序中使用CartItem类型了。

Prisma Schema/Model Prisma模式/模型

Let's add the Prisma schema. Open the prisma/schema.prisma file and add the following:
让我们添加Prisma模式。打开prisma/schema.prisma文件,添加以下内容:
Since there is a relationship between the Cart and User models, also add the following to the User model:
由于CartUser模型之间存在关联,还需要在User模型中添加以下内容:
Let's generate the Prisma client. Open the terminal and run the following command:
让我们生成Prisma客户端。打开终端并运行以下命令:
This will generate the Prisma client.
这将生成Prisma客户端。
Now, let's run the migration:
现在,让我们运行迁移:
This will create a new migration file and apply the changes to the database.
这将创建一个新的迁移文件并将更改应用到数据库。
If you open up Prisma Studio, you will see the new Cart model.
如果你打开Prisma Studio,你会看到新的Cart模型。

3. Add To Cart Component 添加购物车组件

Let's start creating the AddToCart component. This component will be used to add items to the cart on the product page. It will call an action to add the item to the cart. Right now I just want to create the component and connect it to the action. For now, it will just say something like "Add to cart".
让我们开始创建 AddToCart 组件。这个组件将用于在产品页面上将商品添加到购物车。它会调用一个动作来将商品添加到购物车。现在我只想创建组件并将其连接到动作。目前,它只会显示类似"添加到购物车"的文字。

toast Component From ShadCN 来自 ShadCN 的 Toast 组件

We will be using the toast component from ShadCN. This is a component that will display a notification to the user. We will use this to notify the user when an item is added to the cart.
我们将使用来自 ShadCN 的 toast 组件。这是一个向用户显示通知的组件。我们将使用它来通知用户商品已添加到购物车。
Install the component by running the following command:
通过运行以下命令来安装该组件:
🗒️
toast组件已被弃用。请改用sonner组件。 npx shadcn@latest add sonner
We need to add the container for the toast component. Add the following to the app/layout.tsx file:
我们需要为 toast 组件添加容器。将以下内容添加到 app/layout.tsx 文件中:
Embed it right below the {children} tag:
将其嵌入到 {children} 标签的正下方:
🗒️
toast组件已被弃用。请改用sonner组件。 npx shadcn@latest add sonner 完整修改后的代码见小节结尾

Add To Cart Component 添加购物车组件

Create a new file called add-to-cart.tsx in the components/shared/product folder and add the following for now:
components/shared/product 文件夹中创建一个名为 add-to-cart.tsx 的新文件,并暂时添加以下内容:
We made it a client component.
我们将其设为客户端组件。
We are using the CartItem type from the types.ts file. We are using the Omit utility type to remove the cartId property from the CartItem type.
我们使用了来自 types.ts 文件的 CartItem 类型。我们使用 Omit 工具类型来从 CartItem 类型中移除 cartId 属性。
Bring it into the product page. Open the app/(root)/product/[slug]/page.tsx file and add the following import:
将其引入到产品页面。打开 app/(root)/product/[slug]/page.tsx 文件并添加以下导入:
Replace this code:
替换以下代码:
With this code:
使用以下代码:

Component Logic 组件逻辑

Now we need to go into the AddToCart component and add the logic. This will be a very dynamic component. It will be able to add and remove the item from the cart. We will be using the useTransition hook from React, which will allow us to show a loading state while the item is being added or removed to and from the cart. This is not something that you need to do, but it makes for a better user experience. This course includs some of the more advanced features of React.
现在我们需要进入 AddToCart 组件并添加逻辑。这将是一个非常动态的组件。它将能够从购物车中添加和移除商品。我们将使用 React 的 useTransition 钩子,这将允许我们在商品被添加或移除购物车时显示加载状态。这不是你必须做的,但它能提供更好的用户体验。本课程包含一些 React 的高级功能。
We will also implment the toast component for notifications. So we will add to this as we go.
我们还将实现用于通知的 toast 组件。所以我们会在进行过程中添加这个。
For now, add the following imports:
现在,添加以下导入:
Pretty self-explanatory. We are importing our ShadCN components, the types, some icons, the useRouter , and the useToast hook.
这很容易理解。我们正在导入我们的 ShadCN 组件、类型、一些图标、useRouteruseToast 钩子。
Let's add the initializations and state right above the return:
让我们在 return 语句上方添加初始化和状态:
Under that, in the return let's add the button:
在其下方,在 return 中添加按钮:
Finally, add the handleAddToCart function:
最后,添加 handleAddToCart 函数:
We have not created the addItemToCart action yet, but we will do that next. We will then call it. If we get a successful response, we will display a toast message. If we get an error, we will display a toast error.
我们还没有创建 addItemToCart 动作,但我们接下来会这样做。然后我们会调用它。如果我们收到成功的响应,我们将显示一个 toast 消息。如果我们收到错误,我们将显示一个 toast 错误。
Here is the whole AddToCart component:
这是完整的 AddToCart 组件:
🗒️
toast组件已被弃用。改用sonner组件完整代码:

Create The addItemToCart Action 创建 addItemToCart 动作

We aren't going to add any functionality to this action yet. We will just create the action and send a response to test the component.
我们暂时不会为这个动作添加任何功能。我们只会创建动作并发送一个响应来测试组件。
Create a new file at li/actions/cart.actions.ts and add the following:
li/actions/cart.actions.ts 创建一个新文件并添加以下内容:
Bring the action into the AddToCart component:
将该动作引入到 AddToCart 组件中:
Now click the button and you should see the toast message.
现在点击按钮,你应该能看到 toast 消息。
Temporarily change the success to false:
暂时将 success 改为 false:
Click the button and the toast should be red.
点击按钮,toast 应该会显示为红色。
Now that we have the component working, let's start to add the logic to add the item to the cart.
现在组件已经工作了,让我们开始添加将商品添加到购物车的逻辑。

4. Set Session Cart ID In Cookie 在 Cookie 中设置会话购物车 ID

So we have our AddToCart component and the begining of the addItemToCart action. What I want to do now is make it so that when we come to the app, our session cart ID is created and added as a cookie. This will be the user's cart identifier. Because in our action, we need to check for that session cart id in the cookie in order to get the cart items from the database.
现在我们有了 AddToCart 组件和 addItemToCart 动作的初步实现。接下来我要做的是确保当用户访问应用时,会话购物车 ID 会被创建并添加到 Cookie 中。这将是用户的购物车标识符。因为在我们的动作中,需要检查 Cookie 中的会话购物车 ID,以便从数据库获取购物车商品。
We're going to add this logic in a callback in the auth.ts file called authorize, which invokes when a user needs authorization using middleware. You can read more about this callback here - https://authjs.dev/reference/nextjs#authorized.
我们将在 auth.ts 文件中添加一个名为 authorize 的回调函数来实现这个逻辑,当用户使用中间件需要授权时,该回调会被调用。你可以在这里阅读更多关于此回调的信息 - https://authjs.dev/reference/nextjs#authorized。
Since this callback uses middleware, It will only be called if we add a middleware file and reference the auth file.
由于此回调使用中间件,只有当我们添加中间件文件并引用 auth 文件时,它才会被调用。
Create a new file in the root called middleware.ts and add the following:
在根目录创建一个名为 middleware.ts 的新文件,并添加以下内容:
🗒️
注意:Next Js middleware文件约定已被弃用,并已重命名为proxyhttps://nextjs.org/docs/app/api-reference/file-conventions/proxy 在根目录创建一个名为 proxy.ts 的新文件
We are exporting our auth function from the auth.ts file as middleware. Now we can add and use the authorize callback and it will run on every page request unless we specify that we don't want the middleware used on a certain page.
我们将 auth.ts 文件中的 auth 函数作为中间件导出。现在我们可以添加并使用 authorize 回调,它将在每个页面请求时运行,除非我们指定不想在某个页面上使用中间件。
Create a new callback in the auth.ts file:
auth.ts 文件中创建一个新的回调:
Be sure to add the following imports as well:
确保同时添加以下导入:
We are checking if there is a sessionCartId cookie. If not, we generate a new one using a random UUID and set it in the response cookies.This ID will be used to identify the cart for this specific session.
我们检查是否存在 sessionCartId Cookie。如果不存在,我们使用随机 UUID 生成一个新的 ID 并将其设置在响应 Cookie 中。此 ID 将用于标识此特定会话的购物车。
Next, The headers from the current request are cloned into a new Headers object. This is necessary because NextResponse.next() requires a complete request对象, including headers.
接下来,当前请求的标头被克隆到一个新的 Headers 对象中。这是必要的,因为 NextResponse.next() 需要一个完整的请求对象,包括标头。
A new NextResponse object is created to handle the request. NextResponse.next() allows the request to continue to its intended destination but with modifications (like setting cookies).
创建一个新的 NextResponse 对象来处理请求。NextResponse.next() 允许请求继续前往其预期目标,但可以进行修改(如设置 Cookie)。
Then the newly generated sessionCartId is added as a cookie in the response. This ensures the cookie is available for subsequent requests.
然后将新生成的 sessionCartId 作为 Cookie 添加到响应中。这确保 Cookie 可用于后续请求。
We then return the response. If the sessionCartId cookie already exists, the function simply returns true.
然后我们返回响应。如果 sessionCartId Cookie 已存在,函数直接返回 true。
Now, go to the app and in the devtools->application tab you should see the sessionCartId cookie.
现在,打开应用并在开发者工具 -> Application 标签页中,你应该能看到 sessionCartId Cookie。

5. Get Item For Cart 获取购物车商品

We want to be able to add an item to the cart in the database, but first, we have to get the user and find the product in the database. That's what we'll do in this lesson.
我们希望能够将商品添加到数据库中的购物车,但首先,我们需要获取用户并在数据库中找到该商品。这就是本节课要做的内容。
Open the lib/actions/cart.actions.ts and add the following imports:
打开 lib/actions/cart.actions.ts 文件并添加以下导入:
We are bringing in the validators, utility functions, auth file, cookies, revalidatePath, and the prisma client.
我们引入了验证器、工具函数、auth 文件、cookies、revalidatePath 和 prisma 客户端。

Add Item To Cart Action 添加商品到购物车动作

Let's continue with the addItemToCart action. It won't actually add it just yet, but like I said, we need to get the user and get the item.
让我们继续完善 addItemToCart 动作。它实际上还不会添加商品,但正如我所说,我们需要先获取用户和商品信息。
In the try block, let's start by getting the session cart ID from the cookie and then get the user ID from the session. We will add some logs for testing as well.
在 try 块中,让我们先从 Cookie 中获取会话购物车 ID,然后从会话中获取用户 ID。我们还会添加一些日志用于测试。
Add the following for the addItemToCart action:
addItemToCart 动作添加以下内容:
Now click the add to cart button and you should see the session cart ID and user ID in the console. So far, so good.
现在点击"添加到购物车"按钮,你应该能在控制台中看到会话购物车 ID 和用户 ID。到目前为止一切顺利。

Get User Cart Action 获取用户购物车动作

We need to get the user's cart from the database. We will do this in the getMyCart action.
我们需要从数据库中获取用户的购物车。我们将在 getMyCart 动作中完成这个操作。
Under the addItemToCart action, add the following action:
addItemToCart 动作下方,添加以下动作:
Again we are checking for the session cart ID in the cookie. If it doesn't exist, we return undefined. We are also getting the user ID from the session. We are then using the prisma object to find the cart in the database. If the cart doesn't exist, we return undefined. We are then using the convertToPlainObject function to convert the data to a plain object.
我们再次检查 Cookie 中的会话购物车 ID。如果不存在,我们返回 undefined。我们还从会话中获取用户 ID。然后我们使用 prisma 对象在数据库中查找购物车。如果购物车不存在,我们返回 undefined。然后我们使用 convertToPlainObject 函数将数据转换为普通对象。
We are converting the itemsPrice, totalPrice, shippingPrice, and taxPrice to strings because we are using the Decimal type in the database. We need to fdo this to prevent future TypeScript errors.
我们将 itemsPricetotalPriceshippingPricetaxPrice 转换为字符串,因为我们在数据库中使用的是 Decimal 类型。我们需要这样做以防止将来出现 TypeScript 错误。
Now back in the addItemToCart action, let's get the user cart.
现在回到 addItemToCart 动作中,让我们获取用户购物车。
You should see the item requested from the button, the product found in the database and the cart, which right now is undefined.
你应该能看到从按钮请求的商品、在数据库中找到的产品以及购物车(目前为 undefined)。
In the next lesson, we will make it so the item is added to the cart.
在下一节课中,我们将实现将商品添加到购物车的功能。
Here is the full code for the addItemToCart action up to this point:
以下是到目前为止 addItemToCart 动作的完整代码:

6. Price Calculation & Add Item To Database 价格计算与添加商品到数据库

We need to do some calculations on the prices before adding to the database. Let's do that now.
在将商品添加到数据库之前,我们需要对价格进行一些计算。让我们现在开始。

round2 四舍五入函数

We need a function to round numbers to 2 decimal places.
我们需要一个将数字四舍五入到小数点后两位的函数。
Open the lib/utils.ts file and add the following function:
打开 lib/utils.ts 文件并添加以下函数:
The round2 function takes a number or a string that looks like a number and rounds it to 2 decimal places. It takes in a number or string and rounds both to 2 decimal places. It uses Number.EPSILON, which is a very tiny number that helps avoid rounding errors caused by how computers handle floating-point math. Adding this ensures the number is correctly rounded.
round2 函数接受一个数字或看起来像数字的字符串,并将其四舍五入到小数点后两位。它接受数字或字符串,并将两者都四舍五入到小数点后两位。它使用 Number.EPSILON,这是一个非常小的数字,有助于避免计算机处理浮点数学时产生的四舍五入错误。添加这个可以确保数字被正确四舍五入。
value * 100: This moves the decimal point two places to the right. For example 123.456 → 12345.6
value * 100:这将小数点向右移动两位。例如 123.456 → 12345.6
Dividing by 100: This moves the decimal point back to where it was. For example 12346 → 123.46
除以 100:这将小数点移回原来的位置。例如 12346 → 123.46

calcPrice Function calcPrice 函数

We need to calculate the price of the item. We will do this in the calcPrice function. Add this to the lib/actions/cart.actions.ts file right above the addItemToCart function:
我们需要计算商品的价格。我们将在 calcPrice 函数中完成这个操作。将此代码添加到 lib/actions/cart.actions.ts 文件中 addItemToCart 函数的上方:
This function takes an array of items and returns an object with the total price of the items, the shipping price, the tax price, and the total price. We use the round2 function to round the prices to 2 decimal places. We will create this in a minute.
此函数接受一个商品数组,并返回一个包含商品总价、运费、税费和总价格的对象。我们使用 round2 函数将价格四舍五入到小数点后两位。我们马上就会创建这个函数。
The shipping price is $10 if the items price is less than or equal to $100.
如果商品价格小于或等于 $100,运费为 $10。
The tax price is 15% of the items price.
税费是商品价格的 15%。
The total price is the sum of the items price, the shipping price, and the tax price.
总价格是商品价格、运费和税费的总和。
We return an object with the prices rounded to 2 decimal places.
我们返回一个价格四舍五入到小数点后两位的对象。

Add Item To Database 添加商品到数据库

In the addItemToCart function, get rid of the testing logs and the return.
addItemToCart 函数中,删除测试日志和 return 语句。
Under the line if (!product) throw new Error('Product not found'); add the following code:
if (!product) throw new Error('Product not found'); 这一行下方添加以下代码:
We are checking for an existing cart. If it exists, we create a new object with the cart data. We are using the insertCartSchema to validate the data. We are using the calcPrice function to calculate the price of the item. We will create this in a minute It also includes the sessionCartId and the userId from the session object. We then add it to the database. We then revalidate the product page. We then return a success message.
我们正在检查是否存在现有的购物车。如果不存在,我们创建一个包含购物车数据的新对象。我们使用 insertCartSchema 来验证数据。我们使用 calcPrice 函数来计算商品价格。我们马上就会创建这个函数。它还包括来自 session 对象的 sessionCartIduserId。然后我们将其添加到数据库中。接着我们重新验证商品页面。最后我们返回成功消息。

Test It Out 测试一下

Open up Prisma Studio with npx prisma studio and check the database. Before clicking the button, there should be nothing in the Cart table. After clicking the button, there should be a new row in the Cart table with the item you added.
使用 npx prisma studio 打开 Prisma Studio 并检查数据库。在点击按钮之前,Cart 表中应该没有任何内容。点击按钮后,Cart 表中应该有一行新记录,包含您添加的商品。

7. Handle Quantity & Multiple Items 处理数量与多件商品

We need to check if the cart exists because if we have a product in the cart and we go to add another one of the same product, we just want to increase the quantity of the existing item. We also want to add another item if it does not exist.
我们需要检查购物车是否存在,因为如果购物车中已有某个商品,而我们又想添加另一个相同的商品,我们只想增加现有商品的数量。如果商品不存在,我们也希望添加新商品。
Add an else to the if(!cart) statement. Add the following code:
if(!cart) 语句中添加一个 else。添加以下代码:
We are checking to see if the item is already in the cart. We then check to see if the stock is enough to add the item to the cart. If it is, we increase the quantity of the existing item.
我们正在检查商品是否已在购物车中。然后我们检查库存是否足够将该商品添加到购物车。如果足够,我们就增加现有商品的数量。
If the item does not exist in the cart, we check the stock and then we add it.
如果商品不在购物车中,我们检查库存,然后将其添加进去。
Finally, we save the item to the database. We are using the update method to update the cart. We are using the calcPrice function to calculate the price of the item. We are using the revalidatePath function to revalidate the product page. We then return a success message.
最后,我们将商品保存到数据库中。我们使用 update 方法来更新购物车。我们使用 calcPrice 函数来计算商品价格。我们使用 revalidatePath 函数来重新验证商品页面。然后我们返回成功消息。
修改add-to-cart.tsx的返回消息:
Now you should be able to add as many items as you want to the cart. If you look in the database in the Cart table and the items field, you will see the items in the cart. If there is more than one of the same item, the qty will be greater than 1.
现在您应该可以向购物车添加任意数量的商品了。如果您在数据库的 Cart 表和 items 字段中查看,您将看到购物车中的商品。如果同一商品有多个,qty 数量将大于 1。

8. Remove Item from Cart Action 从购物车移除商品操作

We can now add an item to the cart. Now let's add the ability to remove an item from the cart. We need to create a new action for this.
我们现在可以将商品添加到购物车了。接下来让我们添加从购物车移除商品的功能。我们需要为此创建一个新的操作。
Open the lib/actions/cart.actions.ts file and add the following function:
打开 lib/actions/cart.actions.ts 文件并添加以下函数:
We are passing in a product id to remove.
我们传入一个要移除的商品 ID。
We will build this function up in chunks. First, we need to get the session cart id. Add the following code to the try block:
我们将分步构建这个函数。首先,我们需要获取会话购物车 ID。在 try 块中添加以下代码:
Next, we need to get the product from the database:
接下来,我们需要从数据库获取商品信息:
Next, get the user cart:
接下来,获取用户购物车:
See if the cart has the item:
检查购物车中是否有该商品:
We need to check if the quantity is 1 and if so, remove the item. If the quantity is more than 1, then we need to decrease the quantity. Add the following code:
我们需要检查数量是否为 1,如果是,则移除该商品。如果数量大于 1,则需要减少数量。添加以下代码:
Update the database:
更新数据库:
We are using the calcPrice function to calculate the price of the item.
我们使用 calcPrice 函数来计算商品价格。
Revalidate the product page:
重新验证商品页面:
Return success and message:
返回成功状态和消息:
We are returning a message with the product name and whether it was updated or removed from the cart.
我们返回一条包含商品名称以及该商品是已更新还是已从购物车移除的消息。
Here is the full code:
以下是完整代码:

9. Dynamic Cart Button 动态购物车按钮

We now have an action to remove the items from the cart. Now we are going to edit the add-item-to-cart button to show a quantity and a remove button.
我们现在已经有了从购物车移除商品的操作。接下来我们将编辑添加到购物车按钮,使其显示数量和移除按钮。
We need to pass the cart into the button component. So open the product page at app/(root)/product/[slug]/page.tsx and let's import our getMyCart action:
我们需要将购物车传递给按钮组件。因此打开商品页面 app/(root)/product/[slug]/page.tsx 并导入我们的 getMyCart 操作:
then initialize it above the return:
然后在 return 语句上方初始化它:
Now just pass it into the AddToCart component:
现在将其传递给 AddToCart 组件:
Open the components/shared/product/add-to-cart.tsx file and add the cart prop:
打开 components/shared/product/add-to-cart.tsx 文件并添加 cart 属性:
Import the Cart type, Minus icon and the removeFromCart action:
导入 Cart 类型、Minus 图标和 removeFromCart 操作:

Handle Remove From Cart 处理从购物车移除

Add the following function below the handleAddToCart function:
handleAddToCart 函数下方添加以下函数:
We are just calling the removeItemFromCart action and showing a toast message.
我们只是调用 removeItemFromCart 操作并显示一个提示消息。

Show Remove From Cart 显示从购物车移除按钮

We are going to create a variable to let us know if the item exists in the cart. Add the following right above the return statement:
我们将创建一个变量来让我们知道商品是否存在于购物车中。在 return 语句正上方添加以下代码:
Now in the return, let's check for the existItem variable and show a remove button with the minus sign, the quantity and an add button with a plus sign:
现在在 return 中,让我们检查 existItem 变量,并显示一个带有减号的移除按钮、数量以及一个带有加号的添加按钮:
🗒️
代码中 shadcn/ui 的 toast 已弃用,使用sonner 库代码如下:
Now add an item to the cart and you should see the add/remove buttons and the quantity.
现在将一个商品添加到购物车,你应该能看到添加/移除按钮和数量显示。

10. Smooth UI With useTransition Hook useTransition 钩子

We are going to utilize the useTransition hook to handle the state of the button.
我们将使用 useTransition 钩子来处理按钮的状态。

What is useTransition? 什么是 useTransition?

useTransition is a React hook that helps manage UI updates by allowing you to mark certain updates as "transitions." Transitions are typically non-urgent updates that can be deferred to improve user experience (e.g., showing a loading spinner while the update happens).
useTransition 是一个 React 钩子,它通过允许你将某些更新标记为"过渡"来帮助管理 UI 更新。过渡通常是非紧急的更新,可以被延迟以改善用户体验(例如,在更新发生时显示加载旋转器)。
It provides two values:
它提供两个值:
  • isPending: A boolean that indicates whether the transition is ongoing.
  • startTransition: A function that starts the transition.
  • isPending:一个布尔值,指示过渡是否正在进行中。
  • startTransition:一个启动过渡的函数。
We are going to show a spinning loader when the transition is pending.
我们将在过渡挂起时显示一个旋转加载器。
In the AddToCart component, let's import the useTransition hook and the Loader icon:
AddToCart 组件中,让我们导入 useTransition 钩子和 Loader 图标:
Then add the following in the function above the handleAddToCart function:
然后在 handleAddToCart 函数上方的函数中添加以下代码:
  • isPending: A boolean value that indicates whether the transition is still ongoing. This can be used to show a loading spinner or other feedback to the user.
  • startTransition: A function that you wrap around any state updates that you want to handle as a transition. It tells React to delay marking this update as urgent, giving priority to other interactive UI updates.
  • isPending:一个布尔值,指示过渡是否仍在进行中。这可用于向用户显示加载旋转器或其他反馈。
  • startTransition:一个函数,你将其包裹在想要作为过渡处理的任何状态更新周围。它告诉 React 延迟将此更新标记为紧急,优先处理其他交互式 UI 更新。

startTransition Function startTransition 函数

We need to wrap the functionality of handleAddToCart and handleRemoveFromCart functions with the startTransition function.
我们需要用 startTransition 函数包裹 handleAddToCarthandleRemoveFromCart 函数的功能。
Make your handleAddToCart function look like this:
将你的 handleAddToCart 函数改成这样:
We just wrapped the existing functionality with the startTransition function.
我们只是用 startTransition 函数包裹了现有功能。
Do the same for the handleRemoveFromCart function.
handleRemoveFromCart 函数做同样的处理。
We are going to set the disabled attribute of the buttons to isPending and replace the icons with a check for isPending and show a loader if isPending is true.
我们将把按钮的 disabled 属性设置为 isPending,并用检查 isPending 来替换图标,如果 isPendingtrue 则显示加载器。
So now the button will be disabled when the isPending state is true and will show a loading spinner.
所以现在当 isPending 状态为 true 时,按钮将被禁用并显示加载旋转器。

📎 参考文章

  • 一些引用
  • 引用文章
 
💡
欢迎您在底部评论区留言,一起交流~
上一篇
第一节 大脑:重新认识你自己
下一篇
Harness Engineering - 搭建Mini Harness
Loading...