āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/clerk/clerk-docs/reference/hooks/use-plans ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
usePlans()'
description: Access plans in your React application with Clerk's usePlans() hook.
sdk: nextjs, reactThe usePlans() hook provides access to the subscription plans available in your application. It returns a paginated list of plans and includes methods for managing them.
usePlans() accepts a single object with the following properties:
Specifies whether to fetch plans for users or organizations. Defaults to 'user'.
pageSize?numberThe number of plans to fetch per page. Defaults to 10.
initialPage?numberThe page number to start fetching from. Defaults to 1.
infinite?booleanWhen true, enables infinite pagination mode where new pages are appended to existing data. When false, each page replaces the previous data. Defaults to false.
keepPreviousData?booleanWhen true, the previous data will be kept while loading the next page. This helps prevent layout shifts. Defaults to false.
</Properties>
usePlans() returns an object with the following properties:
An array of plans, or null if the data hasn't been loaded yet.
isLoadingbooleanA boolean that indicates whether the initial data is still being fetched.
isFetchingbooleanA boolean that indicates whether any request is still in flight, including background updates.
hasNextPagebooleanA boolean that indicates whether there are more pages available to load.
hasPreviousPagebooleanA boolean that indicates whether there are previous pages available to load.
fetchNext() => Promise<void>A function to fetch the next page of plans.
fetchPrevious() => Promise<void>A function to fetch the previous page of plans.
pageCountnumberThe total number of available pages.
countnumberThe total number of plans available. </Properties>
The following example shows how to fetch and display available plans.
'use client'
import { usePlans } from '@clerk/nextjs/experimental'
function PlansList() {
const { data, isLoading, hasNextPage, fetchNext, hasPreviousPage, fetchPrevious } = usePlans({
for: 'user',
pageSize: 10,
})
if (isLoading) {
return <div>Loading plans...</div>
}
return (
<ul>
{data?.map((plan) => (
<li key={plan.id}>
<h3>{plan.name}</h3>
<p>{plan.description}</p>
<p>Is free plan: {!plan.hasBaseFee ? 'Yes' : 'No'}</p>
<p>
Price per month: {plan.currency} {plan.amountFormatted}
</p>
<p>
Price per year: {plan.currency} {plan.annualAmountFormatted} equivalent to{' '}
{plan.currency} {plan.annualMonthlyAmountFormatted} per month
</p>
<h4>Features:</h4>
<ul>
{plan.features.map((feature) => (
<li key={feature.id}>{feature.name}</li>
))}
</ul>
</li>
))}
{hasNextPage && <button onClick={() => fetchNext()}>Next</button>}
{hasPreviousPage && <button onClick={() => fetchPrevious()}>Previous</button>}
</ul>
)
}
The following example demonstrates how to implement infinite scrolling with plans.
'use client'
import { usePlans } from '@clerk/nextjs/experimental'
function InfinitePlansList() {
const { data, isLoading, hasNextPage, fetchNext } = usePlans({
for: 'user',
infinite: true,
pageSize: 2,
})
if (isLoading) {
return <div>Loading plans...</div>
}
return (
<div>
<ul>
{data?.map((plan) => (
<li key={plan.id}>
<h3>{plan.name}</h3>
<p>{plan.description}</p>
<p>Is free plan: {!plan.hasBaseFee ? 'Yes' : 'No'}</p>
<p>
Price per month: {plan.currency} {plan.amountFormatted}
</p>
<p>
Price per year: {plan.currency} {plan.annualAmountFormatted} equivalent to{' '}
{plan.currency} {plan.annualMonthlyAmountFormatted} per month
</p>
<h4>Features:</h4>
<ul>
{plan.features.map((feature) => (
<li key={feature.id}>{feature.name}</li>
))}
</ul>
</li>
))}
</ul>
{hasNextPage && <button onClick={() => fetchNext()}>Load more plans</button>}
</div>
)
}
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā