Medusa React
Medusa React is a React library that provides a set of utilities and hooks for interacting seamlessly with the Medusa server. It can be used to build custom React-based storefronts or admin dashboards.
Installation
In the directory holding your React-based storefront or admin dashboard, run the following command to install Medusa React:
- npm
- Yarn
npm install medusa-react @tanstack/react-query @medusajs/medusa
yarn add medusa-react @tanstack/react-query @medusajs/medusa
In addition to the medusa-react
Copy to Clipboard library, you need the following libraries:
1. @tanstack/react-query
Copy to Clipboard: medusa-react
Copy to Clipboard is built on top of Tanstack Query. You’ll learn later in this reference how you can use Mutations and Queries with Medusa React.

Versions of Medusa React prior to v4.0.2 used React Query v3 instead of Tanstack Query. Check out [this upgrade guide] to learn how you can update your storefront.
2. @medusajs/medusa
Copy to Clipboard: The core Medusa package. This is used to import types used by Medusa React and while developing with it.

Part of the Medusa roadmap is to move the types into a separate package, removing the need to install the core Medusa package in your storefront or admin dashboard. You can check other items on our roadmap in GitHub Discussions.
Usage
To use the hooks exposed by Medusa React, you need to include the MedusaProvider
Copy to Clipboard somewhere up in your component tree.
The MedusaProvider
Copy to Clipboard requires two props:
baseUrl
Copy to Clipboard: The URL to your Medusa serverqueryClientProviderProps
Copy to Clipboard: An object used to set the Tanstack Query client. The object requires aclient
Copy to Clipboard property, which should be an instance of QueryClient.
For example:
import { MedusaProvider } from "medusa-react"
import Storefront from "./Storefront"
import { QueryClient } from "@tanstack/react-query"
import React from "react"
const queryClient = new QueryClient()
const App = () => {
return (
<MedusaProvider
queryClientProviderProps={{ client: queryClient }}
baseUrl="http://localhost:9000"
>
<Storefront />
</MedusaProvider>
)
}
export default App
In the example above, you wrap the Storefront
Copy to Clipboard component with the MedusaProvider
Copy to Clipboard. Storefront
Copy to Clipboard is assumed to be the top-level component of your storefront, but you can place MedusaProvider
Copy to Clipboard at any point in your tree. Only children of MedusaProvider
Copy to Clipboard can benefit from its hooks.
The Storefront
Copy to Clipboard component and its child components can now use hooks exposed by Medusa React.
MedusaProvider Optional Props
You can also pass the following props to Medusa Provider:
Props | Default | Description |
---|---|---|
apiKey Copy to Clipboard | '' Copy to Clipboard | Optional API key used for authenticating admin requests. |
publishableApiKey Copy to Clipboard | '' Copy to Clipboard | Optional publishable API key used for storefront requests. |
Queries
To fetch data from the Medusa server (in other words, perform GET
Copy to Clipboard requests), you can use Queries. Query hooks simply wrap around Tanstack Query's useQuery
Copy to Clipboard hook to fetch data from your medusa server.
For example, to fetch products from your Medusa server:
import { Product } from "@medusajs/medusa"
import { useProducts } from "medusa-react"
const Products = () => {
const { products, isLoading } = useProducts()
return isLoading ? (
<div>
Loading...
</div>
) : (
<ul>
{products?.map((product: Product) => (
<li key={product.id}>
{product.title}
</li>
))}
</ul>
)
}
export default Products
In the example above, you import the useProducts
Copy to Clipboard hook from medusa-react
Copy to Clipboard. This hook, and every other query hook exposed by medusa-react
Copy to Clipboard, returns everything that useQuery
Copy to Clipboard returns in Tanstack Query, except for the data
Copy to Clipboard field.
Instead of the data
Copy to Clipboard field, the response data is flattened and is part of the hooks’ returned fields. In the example above, the List Products endpoint returns a products
Copy to Clipboard array. So, useProducts
Copy to Clipboard returns a products
Copy to Clipboard array along with other fields returned by useQuery
Copy to Clipboard.
If the request accepts any parameters, they can be passed as parameters to the mutate
Copy to Clipboard request. For example:
const { products } = useProducts({
expand: "variants",
})
You can learn more about using queries in Tanstack Query’s documentation.
Mutations
To create, update, or delete data on the Medusa server (in other words, perform POST
Copy to Clipboard, PUT
Copy to Clipboard, and DELETE
Copy to Clipboard requests), you can use Mutations. Mutation hooks wrap around Tanstack Query's useMutation
Copy to Clipboard to mutate data on your medusa server.
For example, to create a cart:
import { useCreateCart } from "medusa-react"
const Cart = () => {
const createCart = useCreateCart()
const handleClick = () => {
createCart.mutate({}) // create an empty cart
}
return (
<div>
{createCart.isLoading && <div>Loading...</div>}
{!createCart.data?.cart && (
<button onClick={handleClick}>
Create cart
</button>
)}
{createCart.data?.cart?.id && (
<div>Cart ID: {createCart.data?.cart.id}</div>
)}
</div>
)
}
export default Cart
In the example above, you import the useCreateCart
Copy to Clipboard hook from medusa-react
Copy to Clipboard. This hook, and every other mutation hook exposed by medusa-react
Copy to Clipboard, returns everything that useMutation returns. You can also pass the same options you would pass to useMutation
Copy to Clipboard to mutation hooks exposed by medusa-react
Copy to Clipboard.
To create a cart, you call the createCart.mutate
Copy to Clipboard method. In the underlying logic, this method sends a POST
Copy to Clipboard request to the Medusa server to create a cart.
If the request accepts any parameters, they can be passed as parameters to the mutate
Copy to Clipboard request. For example:
createCart.mutate({
region_id,
})
Once the cart is created, you can access it in the data
Copy to Clipboard field returned by the mutation hook. This field includes all data returned in the response.

The example above does not store in the browser the ID of the cart created, so the cart’s data will be gone on release. You would have to do that using the browser’s Local Storage.
Instead of using mutate
Copy to Clipboard, you can use mutateAsync
Copy to Clipboard to receive a Promise that resolves on success or throws on error.
Learn more about how you can use mutations in Tanstack Query’s documentation.
Utilities
medusa-react
Copy to Clipboard exposes a set of utility functions that are mainly used to retrieve or format the price of a product variant.
formatVariantPrice
This utility function can be used to compute the price of a variant for a region and retrieve the formatted amount. For example, $20.00
Copy to Clipboard.
It accepts an object with the following properties:
variant
Copy to Clipboard: A variant object retrieved from the Medusa server. It should mainly include theprices
Copy to Clipboard array in the object.region
Copy to Clipboard: A region object retrieved from the Medusa server.includeTaxes
Copy to Clipboard: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value istrue
Copy to Clipboard.minimumFractionDigits
Copy to Clipboard: (optional) The minimum number of fraction digits to use when formatting the price. This is passed as an option toIntl.NumberFormat
Copy to Clipboard in the underlying layer. You can learn more about this method’s options in MDN’s documentation.maximumFractionDigits
Copy to Clipboard: (optional) The maximum number of fraction digits to use when formatting the price. This is passed as an option toIntl.NumberFormat
Copy to Clipboard which is used within the utility method. You can learn more about this method’s options in MDN’s documentation.locale
Copy to Clipboard: (optional) A string with a BCP 47 language tag. The default value isen-US
Copy to Clipboard. This is passed as a first parameter toIntl.NumberFormat
Copy to Clipboard which is used within the utility method. You can learn more about this method’s parameters in MDN’s documentation.
For example:
import { formatVariantPrice } from "medusa-react"
import { Product, ProductVariant } from "@medusajs/medusa"
const Products = () => {
// ...
return (
<ul>
{products?.map((product: Product) => (
<li key={product.id}>
{product.title}
<ul>
{product.variants.map((variant: ProductVariant) => (
<li key={variant.id}>
{formatVariantPrice({
variant,
region, // should be retrieved earlier
})}
</li>
))}
</ul>
</li>
))}
</ul>
)
}
computeVariantPrice
This utility function can be used to compute the price of a variant for a region and retrieve the amount without formatting. For example, 20
Copy to Clipboard. This method is used by formatVariantPrice
Copy to Clipboard before applying the price formatting.
It accepts an object with the following properties:
variant
Copy to Clipboard: A variant object retrieved from the Medusa server. It should mainly include theprices
Copy to Clipboard array in the variant.region
Copy to Clipboard: A region object retrieved from the Medusa server.includeTaxes
Copy to Clipboard: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value istrue
Copy to Clipboard.
For example:
import { computeVariantPrice } from "medusa-react"
import { Product, ProductVariant } from "@medusajs/medusa"
const Products = () => {
// ...
return (
<ul>
{products?.map((product: Product) => (
<li key={product.id}>
{product.title}
<ul>
{product.variants.map((variant: ProductVariant) => (
<li key={variant.id}>
{computeVariantPrice({
variant,
region, // should be retrieved earlier
})}
</li>
))}
</ul>
</li>
))}
</ul>
)
}
formatAmount
This utility function can be used to compute the price of an amount for a region and retrieve the formatted amount. For example, $20.00
Copy to Clipboard.
The main difference between this utility function and formatVariantPrice
Copy to Clipboard is that you don’t need to pass a complete variant object. This can be used with any number.
It accepts an object with the following properties:
amount
Copy to Clipboard: A number that should be used for computation.region
Copy to Clipboard: A region object retrieved from the Medusa server.includeTaxes
Copy to Clipboard: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value istrue
Copy to Clipboard.minimumFractionDigits
Copy to Clipboard: (optional) The minimum number of fraction digits to use when formatting the price. This is passed as an option toIntl.NumberFormat
Copy to Clipboard in the underlying layer. You can learn more about this method’s options in MDN’s documentation.maximumFractionDigits
Copy to Clipboard: (optional) The maximum number of fraction digits to use when formatting the price. This is passed as an option toIntl.NumberFormat
Copy to Clipboard which is used within the utility method. You can learn more about this method’s options in MDN’s documentation.locale
Copy to Clipboard: (optional) A string with a BCP 47 language tag. The default value isen-US
Copy to Clipboard. This is passed as a first parameter toIntl.NumberFormat
Copy to Clipboard which is used within the utility method. You can learn more about this method’s parameters in MDN’s documentation.
For example:
import { formatAmount } from "medusa-react"
const MyComponent = () => {
// ...
return (
<div>
{formatAmount({
amount,
region, // should be retrieved earlier
})}
</div>
)
}
computeAmount
This utility function can be used to compute the price of an amount for a region and retrieve the amount without formatting. For example, 20
Copy to Clipboard. This method is used by formatAmount
Copy to Clipboard before applying the price formatting.
The main difference between this utility function and computeVariantPrice
Copy to Clipboard is that you don’t need to pass a complete variant object. This can be used with any number.
It accepts an object with the following properties:
amount
Copy to Clipboard: A number that should be used for computation.region
Copy to Clipboard: A region object retrieved from the Medusa server.includeTaxes
Copy to Clipboard: (optional) A boolean value that indicates whether the computed price should include taxes or not. The default value istrue
Copy to Clipboard.
For example:
import { computeAmount } from "medusa-react"
const MyComponent = () => {
// ...
return (
<div>
{computeAmount({
amount,
region, // should be retrieved earlier
})}
</div>
)
}
Content Providers

This is an experimental feature.
To facilitate building custom storefronts, medusa-react
Copy to Clipboard also exposes a CartProvider
Copy to Clipboard and a SessionCartProvider
Copy to Clipboard.
CartProvider
CartProvider
Copy to Clipboard makes use of some of the hooks already exposed by medusa-react
Copy to Clipboard to perform cart operations on the Medusa server. You can use it to create a cart, start the checkout flow, authorize payment sessions, and so on.
It also manages one single global piece of state which represents a cart, exactly like the one created on your medusa backend.
To use CartProvider
Copy to Clipboard, you first have to insert it somewhere in your component tree below the MedusaProvider
Copy to Clipboard.
For example:
import { CartProvider, MedusaProvider } from "medusa-react"
import Storefront from "./Storefront"
import { QueryClient } from "@tanstack/react-query"
import React from "react"
const queryClient = new QueryClient()
function App() {
return (
<MedusaProvider
queryClientProviderProps={{ client: queryClient }}
baseUrl="http://localhost:9000"
>
<CartProvider>
<Storefront />
</CartProvider>
</MedusaProvider>
)
}
export default App
Then, in any of the child components, you can use the useCart
Copy to Clipboard hook exposed by medusa-react
Copy to Clipboard to get access to cart operations and data.
The useCart
Copy to Clipboard hook returns an object with the following properties:
cart
Copy to Clipboard: A state variable holding the cart object. This is set if thecreateCart
Copy to Clipboard mutation is executed or ifsetCart
Copy to Clipboard is manually used.setCart
Copy to Clipboard: A state function used to set the cart object.totalItems
Copy to Clipboard: The number of items in the cart.createCart
Copy to Clipboard: A mutation used to create a cart.updateCart
Copy to Clipboard: A mutation used to update a cart’s details such as region, customer email, shipping address, and more.startCheckout
Copy to Clipboard: A mutation used to initialize payment sessions during checkout.pay
Copy to Clipboard: A mutation used to select a payment provider during checkout.addShippingMethod
Copy to Clipboard: A mutation used to add a shipping method to the cart during checkout.completeCheckout
Copy to Clipboard: A mutation used to complete the cart and place the order.
For example:
import * as React from "react"
import { useCart } from "medusa-react"
const Cart = () => {
const handleClick = () => {
createCart.mutate({}) // create an empty cart
}
const { cart, createCart } = useCart()
return (
<div>
{createCart.isLoading && <div>Loading...</div>}
{!cart?.id && (
<button onClick={handleClick}>
Create cart
</button>
)}
{cart?.id && (
<div>Cart ID: {cart.id}</div>
)}
</div>
)
}
export default Cart
In the example above, you retrieve the createCart
Copy to Clipboard mutation and cart
Copy to Clipboard state object using the useCart
Copy to Clipboard hook. If the cart
Copy to Clipboard is not set, a button is shown. When the button is clicked, the createCart
Copy to Clipboard mutation is executed, which interacts with the server and creates a new cart.
After the cart is created, the cart
Copy to Clipboard state variable is set and its ID is shown instead of the button.

The example above does not store in the browser the ID of the cart created, so the cart’s data will be gone on release. You would have to do that using the browser’s Local Storage.
SessionProvider
Unlike the CartProvider
Copy to Clipboard, SessionProvider
Copy to Clipboard never interacts with the Medusa server. It can be used to implement the user experience related to managing a cart’s items. Its state variables are JavaScript objects living in the browser, but are in no way communicated with the server.
You can use the SessionProvider
Copy to Clipboard as a lightweight client-side cart functionality. It’s not stored in any database or on the Medusa server.
To use SessionProvider
Copy to Clipboard, you first have to insert it somewhere in your component tree below the MedusaProvider
Copy to Clipboard.
For example:
import { SessionProvider, MedusaProvider } from "medusa-react"
import Storefront from "./Storefront"
import { QueryClient } from "@tanstack/react-query"
import React from "react"
const queryClient = new QueryClient()
const App = () => {
return (
<MedusaProvider
queryClientProviderProps={{ client: queryClient }}
baseUrl="http://localhost:9000"
>
<SessionProvider>
<Storefront />
</SessionProvider>
</MedusaProvider>
)
}
export default App
Then, in any of the child components, you can use the useSessionHook
Copy to Clipboard hook exposed by medusa-react
Copy to Clipboard to get access to client-side cart item functionalities.
For example:
const Products = () => {
const { addItem } = useSessionCart()
// ...
function addToCart(variant: ProductVariant) {
addItem({
variant: variant,
quantity: 1,
})
}
}