Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

React Hooks

Payload provides a variety of powerful React Hooks that can be used within your own Custom Components, such as Custom Fields. With them, you can interface with Payload itself to build just about any type of complex customization you can think of.

useField

The useField hook is used internally within all field components. It manages sending and receiving a field's state from its parent form. When you build a Custom Field Component, you will be responsible for sending and receiving the field's value to and from the form yourself.

To do so, import the useField hook as follows:

1
'use client'
2
import type { TextFieldClientComponent } from 'payload'
3
import { useField } from '@payloadcms/ui'
4
5
export const CustomTextField: TextFieldClientComponent = ({ path }) => {
6
const { value, setValue } = useField({ path })
7
8
return (
9
<div>
10
<p>
11
{path}
12
</p>
13
<input
14
onChange={(e) => { setValue(e.target.value) }}
15
value={value}
16
/>
17
</div>
18
)
19
}

The useField hook accepts the following arguments:

Property

Description

path

If you do not provide a path, name will be used instead. This is the path to the field in the form data.

validate

A validation function executed client-side before submitting the form to the server. Different than Field-level Validation which runs strictly on the server.

disableFormData

If true, the field will not be included in the form data when the form is submitted.

hasRows

If true, the field will be treated as a field with rows. This is useful for fields like array and blocks.

The useField hook returns the following object:

1
type FieldType<T> = {
2
errorMessage?: string
3
errorPaths?: string[]
4
filterOptions?: FilterOptionsResult
5
formInitializing: boolean
6
formProcessing: boolean
7
formSubmitted: boolean
8
initialValue?: T
9
path: string
10
permissions: FieldPermissions
11
readOnly?: boolean
12
rows?: Row[]
13
schemaPath: string
14
setValue: (val: unknown, disableModifyingForm?: boolean) => void
15
showError: boolean
16
valid?: boolean
17
value: T
18
}

useFormFields

There are times when a custom field component needs to have access to data from other fields, and you have a few options to do so. The useFormFields hook is a powerful and highly performant way to retrieve a form's field state, as well as to retrieve the dispatchFields method, which can be helpful for setting other fields' form states from anywhere within a form.

Thanks to the awesome package use-context-selector, you can retrieve a specific field's state easily. This is ideal because you can ensure you have an up-to-date field state, and your component will only re-render when that field's state changes.

You can pass a Redux-like selector into the hook, which will ensure that you retrieve only the field that you want. The selector takes an argument with type of [fields: Fields, dispatch: React.Dispatch<Action>]].

1
'use client'
2
import { useFormFields } from '@payloadcms/ui'
3
4
const MyComponent: React.FC = () => {
5
// Get only the `amount` field state, and only cause a rerender when that field changes
6
const amount = useFormFields(([fields, dispatch]) => fields.amount)
7
8
// Do the same thing as above, but to the `feePercentage` field
9
const feePercentage = useFormFields(([fields, dispatch]) => fields.feePercentage)
10
11
if (typeof amount?.value !== 'undefined' && typeof feePercentage?.value !== 'undefined') {
12
return <span>The fee is ${(amount.value * feePercentage.value) / 100}</span>
13
}
14
}

useAllFormFields

To retrieve more than one field, you can use the useAllFormFields hook. Your component will re-render when any field changes, so use this hook only if you absolutely need to. Unlike the useFormFields hook, this hook does not accept a "selector", and it always returns an array with type of [fields: Fields, dispatch: React.Dispatch<Action>]].

You can do lots of powerful stuff by retrieving the full form state, like using built-in helper functions to reduce field state to values only, or to retrieve sibling data by path.

1
'use client'
2
import { useAllFormFields } from '@payloadcms/ui'
3
import { reduceFieldsToValues, getSiblingData } from 'payload/shared'
4
5
const ExampleComponent: React.FC = () => {
6
// the `fields` const will be equal to all fields' state,
7
// and the `dispatchFields` method is usable to send field state up to the form
8
const [fields, dispatchFields] = useAllFormFields();
9
10
// Pass in fields, and indicate if you'd like to "unflatten" field data.
11
// The result below will reflect the data stored in the form at the given time
12
const formData = reduceFieldsToValues(fields, true);
13
14
// Pass in field state and a path,
15
// and you will be sent all sibling data of the path that you've specified
16
const siblingData = getSiblingData(fields, 'someFieldName');
17
18
return (
19
// return some JSX here if necessary
20
)
21
};

Updating other fields' values

If you are building a Custom Component, then you should use setValue which is returned from the useField hook to programmatically set your field's value. But if you're looking to update another field's value, you can use dispatchFields returned from useFormFields.

You can send the following actions to the dispatchFields function.

Action

Description

ADD_ROW

Adds a row of data (useful in array / block field data)

DUPLICATE_ROW

Duplicates a row of data (useful in array / block field data)

MODIFY_CONDITION

Updates a field's conditional logic result (true / false)

MOVE_ROW

Moves a row of data (useful in array / block field data)

REMOVE

Removes a field from form state

REMOVE_ROW

Removes a row of data from form state (useful in array / block field data)

REPLACE_STATE

Completely replaces form state

UPDATE

Update any property of a specific field's state

To see types for each action supported within the dispatchFields hook, check out the Form types here.

useForm

The useForm hook can be used to interact with the form itself, and sends back many methods that can be used to reactively fetch form state without causing rerenders within your components each time a field is changed. This is useful if you have action-based callbacks that your components fire, and need to interact with form state based on a user action.

The useForm hook returns an object with the following properties:

ActionDescriptionExample

fields

Deprecated. This property cannot be relied on as up-to-date.

submit

Method to trigger the form to submit

dispatchFields

Dispatch actions to the form field state

validateForm

Trigger a validation of the form state

createFormData

Create a multipart/form-data object from the current form's state

disabled

Boolean denoting whether or not the form is disabled

getFields

Gets all fields from state

getField

Gets a single field from state by path

getData

Returns the data stored in the form

getSiblingData

Returns form sibling data for the given field path

setModified

Set the form's modified state

setProcessing

Set the form's processing state

setSubmitted

Set the form's submitted state

formRef

The ref from the form HTML element

reset

Method to reset the form to its initial state

addFieldRow

Method to add a row on an array or block field

removeFieldRow

Method to remove a row from an array or block field

replaceFieldRow

Method to replace a row from an array or block field

useCollapsible

The useCollapsible hook allows you to control parent collapsibles:

Property

Description

isCollapsed

State of the collapsible. true if open, false if collapsed.

isVisible

If nested, determine if the nearest collapsible is visible. true if no parent is closed, false otherwise.

toggle

Toggles the state of the nearest collapsible.

isWithinCollapsible

Determine when you are within another collapsible.

Example:

1
'use client'
2
import React from 'react'
3
4
import { useCollapsible } from '@payloadcms/ui'
5
6
const CustomComponent: React.FC = () => {
7
const { isCollapsed, toggle } = useCollapsible()
8
9
return (
10
<div>
11
<p className="field-type">I am {isCollapsed ? 'closed' : 'open'}</p>
12
<button onClick={toggle} type="button">
13
Toggle
14
</button>
15
</div>
16
)
17
}

useDocumentInfo

The useDocumentInfo hook provides information about the current document being edited, including the following:

Property

Description

currentEditor

The user currently editing the document.

docConfig

Either the Collection or Global config of the document, depending on what is being edited.

documentIsLocked

Whether the document is currently locked by another user.

id

If the doc is a collection, its ID will be returned

getDocPermissions

Method to retrieve document-level user preferences.

getDocPreferences

Method to retrieve document-level user preferences.

hasPublishedDoc

Whether the document has a published version.

incrementVersionCount

Method to increment the version count of the document.

preferencesKey

The preferences key to use when interacting with document-level user preferences.

versions

Versions of the current doc.

unpublishedVersions

Unpublished versions of the current doc.

publishedDoc

The currently published version of the doc being edited.

getVersions

Method to retrieve document versions.

docPermissions

The current documents permissions. Collection document permissions fallback when no id is present (i.e. on create).

versionCount

The current version count of the document.

Example:

1
'use client'
2
import { useDocumentInfo } from '@payloadcms/ui'
3
4
const LinkFromCategoryToPosts: React.FC = () => {
5
const { id } = useDocumentInfo()
6
7
// id will be undefined on the create form
8
if (!id) {
9
return null
10
}
11
12
return (
13
<a href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`}>
14
View posts
15
</a>
16
)
17
}

useListQuery

The useListQuery hook is used to subscribe to the data, current query, and other properties used within the List View. You can use this hook within any Custom Component rendered within the List View.

1
'use client'
2
import { useListQuery } from '@payloadcms/ui'
3
4
const MyComponent: React.FC = () => {
5
const { data, query } = useListQuery()
6
7
// ...
8
}

The useListQuery hook returns an object with the following properties:

Property

Description

data

The data that is being displayed in the List View.

defaultLimit

The default limit of items to display in the List View.

defaultSort

The default sort order of items in the List View.

handlePageChange

A method to handle page changes in the List View.

handlePerPageChange

A method to handle per page changes in the List View.

handleSearchChange

A method to handle search changes in the List View.

handleSortChange

A method to handle sort changes in the List View.

handleWhereChange

A method to handle where changes in the List View.

query

The current query that is being used to fetch the data in the List View.

useLocale

In any Custom Component you can get the selected locale object with the useLocale hook. useLocale gives you the full locale object, consisting of a label, rtl(right-to-left) property, and then code. Here is a simple example:

1
'use client'
2
import { useLocale } from '@payloadcms/ui'
3
4
const Greeting: React.FC = () => {
5
const locale = useLocale()
6
7
const trans = {
8
en: 'Hello',
9
es: 'Hola',
10
}
11
12
return <span> {trans[locale.code]} </span>
13
}

useAuth

Useful to retrieve info about the currently logged in user as well as methods for interacting with it. It sends back an object with the following properties:

Property

Description

user

The currently logged in user

logOut

A method to log out the currently logged in user

refreshCookie

A method to trigger the silent refreshing of a user's auth token

setToken

Set the token of the user, to be decoded and used to reset the user and token in memory

token

The logged in user's token (useful for creating preview links, etc.)

refreshPermissions

Load new permissions (useful when content that effects permissions has been changed)

permissions

The permissions of the current user

1
'use client'
2
import { useAuth } from '@payloadcms/ui'
3
import type { User } from '../payload-types.ts'
4
5
const Greeting: React.FC = () => {
6
const { user } = useAuth<User>()
7
8
return <span>Hi, {user.email}!</span>
9
}

useConfig

Used to retrieve the Payload Client Config.

1
'use client'
2
import { useConfig } from '@payloadcms/ui'
3
4
const MyComponent: React.FC = () => {
5
const { config } = useConfig()
6
7
return <span>{config.serverURL}</span>
8
}

useEditDepth

Sends back how many editing levels "deep" the current component is. Edit depth is relevant while adding new documents / editing documents in modal windows and other cases.

1
'use client'
2
import { useEditDepth } from '@payloadcms/ui'
3
4
const MyComponent: React.FC = () => {
5
const editDepth = useEditDepth()
6
7
return <span>My component is {editDepth} levels deep</span>
8
}

usePreferences

Returns methods to set and get user preferences. More info can be found here.

useTheme

Returns the currently selected theme (light, dark or auto), a set function to update it and a boolean autoMode, used to determine if the theme value should be set automatically based on the user's device preferences.

1
'use client'
2
import { useTheme } from '@payloadcms/ui'
3
4
const MyComponent: React.FC = () => {
5
const { autoMode, setTheme, theme } = useTheme()
6
7
return (
8
<>
9
<span>
10
The current theme is {theme} and autoMode is {autoMode}
11
</span>
12
<button
13
type="button"
14
onClick={() => setTheme((prev) => (prev === 'light' ? 'dark' : 'light'))}
15
>
16
Toggle theme
17
</button>
18
</>
19
)
20
}

useTableColumns

Returns methods to manipulate table columns

1
'use client'
2
import { useTableColumns } from '@payloadcms/ui'
3
4
const MyComponent: React.FC = () => {
5
const { setActiveColumns } = useTableColumns()
6
7
const resetColumns = () => {
8
setActiveColumns(['id', 'createdAt', 'updatedAt'])
9
}
10
11
return (
12
<button type="button" onClick={resetColumns}>
13
Reset columns
14
</button>
15
)
16
}

useDocumentEvents

The useDocumentEvents hook provides a way of subscribing to cross-document events, such as updates made to nested documents within a drawer. This hook will report document events that are outside the scope of the document currently being edited. This hook provides the following:

Property

Description

mostRecentUpdate

An object containing the most recently updated document. It contains the entitySlug, id (if collection), and updatedAt properties

reportUpdate

A method used to report updates to documents. It accepts the same arguments as the mostRecentUpdate property.

Example:

1
'use client'
2
import { useDocumentEvents } from '@payloadcms/ui'
3
4
const ListenForUpdates: React.FC = () => {
5
const { mostRecentUpdate } = useDocumentEvents()
6
7
return <span>{JSON.stringify(mostRecentUpdate)}</span>
8
}
Next

Customizing CSS & SCSS