Product Hooks - Admin Components

Note: These hooks are available since Medusa v2.21.0.

The product hooks fetch and mutate products and their variants in the Medusa backend. To fetch variants across all products, use the product variant hooks instead.

Code
1import {2  productsQueryKeys,3  useCreateProduct,4  useDeleteProduct,5  useDeleteVariantLazy,6  useProduct,7  useProductVariants,8  useProducts,9  useUpdateProduct,10  useUpdateProductVariantsBatch,11  variantsQueryKeys,12} from "@medusajs/dashboard/hooks"

These hooks are built on TanStack Query. Use them in your widgets and UI routes.


useProducts#

Fetches a paginated list of products.

Code
1const { products, count, isPending } = useProducts({2  limit: 20,3})

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useQuery result.

Loading...

useProduct#

Fetches a single product by ID.

Code
1const { product, isPending } = useProduct(productId, {2  fields: "+variants.*",3})

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useQuery result.

Loading...

useProductVariants#

Fetches the variants of a specific product. The first parameter is the product's ID, not a query object.

Code
1const { variants, count } = useProductVariants(2  productId,3  { limit: 20 }4)

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useQuery result.

Loading...

useCreateProduct#

Creates a product. On success, the hook invalidates the product lists, along with the inventory item and product option lists, since creating a product can create those resources too.

Code
1const { mutateAsync, isPending } = useCreateProduct()2
3const handleCreate = async () => {4  const { product } = await mutateAsync({5    title: "Shirt",6    options: [7      { title: "Size", values: ["S", "M"] },8    ],9  })10}

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useMutation result.

Loading...

useUpdateProduct#

Updates a product. The hook requests the updated product without its relations, so the response holds the product's own fields only. On success, it invalidates the product lists and the product's detail query.

Code
1const { mutateAsync } = useUpdateProduct(productId)2
3const handleUpdate = async () => {4  await mutateAsync({ title: "New title" })5}

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useMutation result.

Loading...

useDeleteProduct#

Deletes a product. On success, the hook invalidates the product lists, the product's detail query, and the product option lists.

Code
1const { mutateAsync } = useDeleteProduct(productId)2
3const handleDelete = async () => {4  await mutateAsync()5}

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useMutation result.

Loading...

useUpdateProductVariantsBatch#

Updates multiple variants of a product in one request. The payload is the array of variant updates, and the hook wraps it in the batch request's update field for you.

Code
1const { mutateAsync } =2  useUpdateProductVariantsBatch(productId)3
4const handleUpdate = async () => {5  await mutateAsync([6    { id: variantId, title: "Large" },7  ])8}

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useMutation result.

Loading...

useDeleteVariantLazy#

Deletes a variant of a product. The hook is bound to the product only, so you pass the variant's ID when you call the mutation. That makes it useful when one component deletes any of a product's variants.

Code
1const { mutateAsync } = useDeleteVariantLazy(productId)2
3const handleDelete = async (variantId: string) => {4  await mutateAsync({ variantId })5}

Parameters#

Loading...

Returns#

Along with the following, the hook returns the rest of TanStack Query's useMutation result.

Loading...

productsQueryKeys#

A TanStack Query key factory for product queries. Use it to invalidate cached product data after you change a product.

It provides all, lists(), list(query), details(), and detail(id, query).

Code
1import { useQueryClient } from "@tanstack/react-query"2import {3  productsQueryKeys,4} from "@medusajs/dashboard/hooks"5
6const Widget = () => {7  const queryClient = useQueryClient()8
9  const refreshProduct = (id: string) => {10    queryClient.invalidateQueries({11      queryKey: productsQueryKeys.detail(id),12    })13  }14
15  // ...16}

variantsQueryKeys#

A TanStack Query key factory for the variants of a product, which is the factory that useProductVariants uses. It's separate from productVariantQueryKeys, which the product variant hooks use.

Code
1import { useQueryClient } from "@tanstack/react-query"2import {3  variantsQueryKeys,4} from "@medusajs/dashboard/hooks"5
6const Widget = () => {7  const queryClient = useQueryClient()8
9  const refreshVariants = () => {10    queryClient.invalidateQueries({11      queryKey: variantsQueryKeys.lists(),12    })13  }14
15  // ...16}
Was this page helpful?
Ask Bloom
For assistance in your development, use Claude Code Plugins or Docs MCP server in Cursor, VSCode, etc...FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break
⇧↵