diff --git a/docs/02-app/01-building-your-application/04-caching/index.mdx b/docs/02-app/01-building-your-application/04-caching/index.mdx index 193c582c2c56d..2fd73456268de 100644 --- a/docs/02-app/01-building-your-application/04-caching/index.mdx +++ b/docs/02-app/01-building-your-application/04-caching/index.mdx @@ -345,7 +345,7 @@ There are two ways you can invalidate the Router Cache: - In a **Server Action**: - Revalidating data on-demand by path with ([`revalidatePath`](/docs/app/api-reference/functions/revalidatePath)) or by cache tag with ([`revalidateTag`](/docs/app/api-reference/functions/revalidateTag)) - - Using [`cookies.set`](/docs/app/api-reference/functions/cookies#cookiessetname-value-options) or [`cookies.delete`](/docs/app/api-reference/functions/cookies#deleting-cookies) invalidates the Router Cache to prevent routes that use cookies from becoming stale (e.g. authentication). + - Using [`cookies.set`](/docs/app/api-reference/functions/cookies#methods) or [`cookies.delete`](/docs/app/api-reference/functions/cookies#methods) invalidates the Router Cache to prevent routes that use cookies from becoming stale (e.g. authentication). - Calling [`router.refresh`](/docs/app/api-reference/functions/use-router) will invalidate the Router Cache and make a new request to the server for the current route. ### Opting out diff --git a/docs/02-app/01-building-your-application/12-examples/index.mdx b/docs/02-app/01-building-your-application/12-examples/index.mdx index 65fcab269faf4..2974f30349646 100644 --- a/docs/02-app/01-building-your-application/12-examples/index.mdx +++ b/docs/02-app/01-building-your-application/12-examples/index.mdx @@ -30,7 +30,7 @@ description: Examples of popular Next.js UI patterns and use cases. - [Passing additional values](/docs/app/building-your-application/data-fetching/server-actions-and-mutations#passing-additional-arguments) - [Revalidating data](/docs/app/building-your-application/data-fetching/server-actions-and-mutations#revalidating-data) - [Redirecting](/docs/app/building-your-application/data-fetching/server-actions-and-mutations#redirecting) -- [Setting cookies](/docs/app/api-reference/functions/cookies#cookiessetname-value-options) +- [Setting cookies](/docs/app/api-reference/functions/cookies#methods) - [Deleting cookies](/docs/app/api-reference/functions/cookies#deleting-cookies) ### Metadata diff --git a/docs/02-app/02-api-reference/04-functions/cookies.mdx b/docs/02-app/02-api-reference/04-functions/cookies.mdx index 046801e3f39e0..116c03a253dfc 100644 --- a/docs/02-app/02-api-reference/04-functions/cookies.mdx +++ b/docs/02-app/02-api-reference/04-functions/cookies.mdx @@ -1,20 +1,90 @@ --- title: cookies description: API Reference for the cookies function. -related: - title: Next Steps - description: For more information on what to do next, we recommend the following sections - links: - - app/building-your-application/data-fetching/server-actions-and-mutations --- The `cookies` function allows you to read the HTTP incoming request cookies from a [Server Component](/docs/app/building-your-application/rendering/server-components) or write outgoing request cookies in a [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers). -> **Good to know**: `cookies()` is a **[Dynamic Function](/docs/app/building-your-application/rendering/server-components#dynamic-functions)** whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into **[dynamic rendering](/docs/app/building-your-application/rendering/server-components#dynamic-rendering)** at request time. +```tsx filename="app/page.tsx" +import { cookies } from 'next/headers' + +export default function Page() { + const cookieStore = cookies() + const theme = cookieStore.get('theme') + return '...' +} +``` + +```js filename="app/page.js" +import { cookies } from 'next/headers' + +export default function Page() { + const cookieStore = cookies() + const theme = cookieStore.get('theme') + return '...' +} +``` + +## Reference + +### Methods + +The following methods are available: + +| Method | Return Type | Description | +| --------------------------- | ---------------- | ------------------------------------------------------------------------------- | +| `get('name')` | Object | Accepts a cookie name and returns an object with the name and value. | +| `getAll()` | Array of objects | Returns a list of all the cookies with a matching name. | +| `has('name')` | Boolean | Accepts a cookie name and returns a boolean based on if the cookie exists. | +| `set(name, value, options)` | - | Accepts a cookie name, value, and options and sets the outgoing request cookie. | +| `delete(name)` | - | Accepts a cookie name and deletes the cookie. | +| `clear()` | - | Deletes all cookies. | +| `toString()` | String | Returns a string representation of the cookies. | + +### Options + +When setting a cookie, the following properties from the `options` object are supported: + +| Option | Type | Description | +| ----------------- | -------------------------------------- | ---------------------------------------------------------------------------------- | +| `name` | String | Specifies the name of the cookie. | +| `value` | String | Specifies the value to be stored in the cookie. | +| `expires` | Date | Defines the exact date when the cookie will expire. | +| `maxAge` | Number | Sets the cookie’s lifespan in seconds. | +| `domain` | String | Specifies the domain where the cookie is available. | +| `path` | String | Limits the cookie's scope to a specific path within the domain. | +| `secure` | Boolean, | Ensures the cookie is sent only over HTTPS connections for added security. | +| `httpOnly` | Boolean | Restricts the cookie to HTTP requests, preventing client-side access. | +| `sameSite` | Boolean, `'lax'`, `'strict'`, `'none'` | Controls the cookie's cross-site request behavior. | +| `priority` | String (`"low"`, `"medium"`, `"high"`) | Specifies the cookie's priority | +| `encode('value')` | Function | Specifies a function that will be used to encode a cookie's value. | +| `partitioned` | Boolean | Indicates whether the cookie is [partitioned](https://github.com/privacycg/CHIPS). | + +To learn more about these options, see the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies). + +## Caveats + +- `cookies()` is a **[Dynamic Function](/docs/app/building-your-application/rendering/server-components#dynamic-functions)** whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into **[dynamic rendering](/docs/app/building-your-application/rendering/server-components#dynamic-rendering)**. +- The `.delete()` method can only be called: + - In a [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers). + - If it belongs to the same domain from which `.set()` is called. Additionally, the code must be executed on the same protocol (HTTP or HTTPS) as the cookie you want to delete. +- HTTP does not allow setting cookies after streaming starts, so you must use `.set()` in a [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers). -## `cookies().get(name)` +## Examples -A method that takes a cookie name and returns an object with name and value. If a cookie with `name` isn't found, it returns `undefined`. If multiple cookies match, it will only return the first match. +### Getting a cookie + +You can use the `cookies().get('name')` method to get a single cookie: + +```tsx filename="app/page.tsx" +import { cookies } from 'next/headers' + +export default function Page() { + const cookieStore = cookies() + const theme = cookieStore.get('theme') + return '...' +} +``` ```jsx filename="app/page.js" import { cookies } from 'next/headers' @@ -26,11 +96,11 @@ export default function Page() { } ``` -## `cookies().getAll()` +### Getting all cookies -A method that is similar to `get`, but returns a list of all the cookies with a matching `name`. If `name` is unspecified, it returns all the available cookies. +You can use the `cookies().getAll()` method to get all cookies with a matching name. If `name` is unspecified, it returns all the available cookies. -```jsx filename="app/page.js" +```tsx filename="app/page.tsx" import { cookies } from 'next/headers' export default function Page() { @@ -44,25 +114,42 @@ export default function Page() { } ``` -## `cookies().has(name)` - -A method that takes a cookie name and returns a `boolean` based on if the cookie exists (`true`) or not (`false`). - ```jsx filename="app/page.js" import { cookies } from 'next/headers' export default function Page() { const cookieStore = cookies() - const hasCookie = cookieStore.has('theme') - return '...' + return cookieStore.getAll().map((cookie) => ( +
+

Name: {cookie.name}

+

Value: {cookie.value}

+
+ )) } ``` -## `cookies().set(name, value, options)` +### Setting a cookie -A method that takes a cookie name, value, and options and sets the outgoing request cookie. +You can use the `cookies().set(name, value, options)` method in a [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers) to set a cookie. The [`options` object](#options) is optional. -> **Good to know**: HTTP does not allow setting cookies after streaming starts, so you must use `.set()` in a [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers). +```tsx filename="app/actions.ts" +'use server' + +import { cookies } from 'next/headers' + +async function create(data) { + cookies().set('name', 'lee') + // or + cookies().set('name', 'lee', { secure: true }) + // or + cookies().set({ + name: 'name', + value: 'lee', + httpOnly: true, + path: '/', + }) +} +``` ```js filename="app/actions.js" 'use server' @@ -83,17 +170,37 @@ async function create(data) { } ``` -## Deleting cookies +### Check if a cookie exists -> **Good to know**: You can only delete cookies in a [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers). +You can use the `cookies().has(name)` method to check if a cookie exists: -There are several options for deleting a cookie: +```tsx filename="app/page.ts" +import { cookies } from 'next/headers' -### `cookies().delete(name)` +export default function Page() { + const cookieStore = cookies() + const hasCookie = cookieStore.has('theme') + return '...' +} +``` -You can explicitly delete a cookie with a given name. +```jsx filename="app/page.js" +import { cookies } from 'next/headers' -```js filename="app/actions.js" +export default function Page() { + const cookieStore = cookies() + const hasCookie = cookieStore.has('theme') + return '...' +} +``` + +### Deleting cookies + +There are three ways you can delete a cookie. + +1. Using the `delete()` method: + +```tsx filename="app/actions.ts" 'use server' import { cookies } from 'next/headers' @@ -103,25 +210,27 @@ async function delete(data) { } ``` -### `cookies().set(name, '')` - -Alternatively, you can set a new cookie with the same name and an empty value. - ```js filename="app/actions.js" 'use server' import { cookies } from 'next/headers' async function delete(data) { - cookies().set('name', '') + cookies().delete('name') } ``` -> **Good to know**: `.set()` is only available in a [Server Action](/docs/app/building-your-application/data-fetching/server-actions-and-mutations) or [Route Handler](/docs/app/building-your-application/routing/route-handlers). +2. Setting a new cookie with the same name and an empty value: -### `cookies().set(name, value, { maxAge: 0 })` +```tsx filename="app/actions.ts" +'use server' -Setting `maxAge` to 0 will immediately expire a cookie. `maxAge` accepts a value in seconds. +import { cookies } from 'next/headers' + +async function delete(data) { + cookies().set('name', '') +} +``` ```js filename="app/actions.js" 'use server' @@ -129,13 +238,21 @@ Setting `maxAge` to 0 will immediately expire a cookie. `maxAge` accepts a value import { cookies } from 'next/headers' async function delete(data) { - cookies().set('name', 'value', { maxAge: 0 }) + cookies().set('name', '') } ``` -### `cookies().set(name, value, { expires: timestamp })` +3. Setting the `maxAge` to 0 will immediately expire a cookie. `maxAge` accepts a value in seconds. -Setting `expires` to any value in the past will immediately expire a cookie. +```tsx filename="app/actions.ts" +'use server' + +import { cookies } from 'next/headers' + +async function delete(data) { + cookies().set('name', 'value', { maxAge: 0 }) +} +``` ```js filename="app/actions.js" 'use server' @@ -143,13 +260,10 @@ Setting `expires` to any value in the past will immediately expire a cookie. import { cookies } from 'next/headers' async function delete(data) { - const oneDay = 24 * 60 * 60 * 1000 - cookies().set('name', 'value', { expires: Date.now() - oneDay }) + cookies().set('name', 'value', { maxAge: 0 }) } ``` -> **Good to know**: You can only delete cookies that belong to the same domain from which `.set()` is called. Additionally, the code must be executed on the same protocol (HTTP or HTTPS) as the cookie you want to delete. - ## Version History | Version | Changes |