React Hooks

Payload provides a variety of powerful hooks that can be used within your own React components. With them, you can interface with Payload itself and build just about any type of complex customization you can think of—directly in familiar React code.

useField

The useField hook is used internally within every applicable Payload field component, and it manages sending and receiving a field's state from its parent form.

Outside of internal use, its most common use-case is in custom Field components. When you build a custom React Field component, you'll be responsible for sending and receiving the field's value from the form itself. To do so, import the useField hook as follows:

1
import { useField } from 'payload/components/forms'
2
3
type Props = { path: string }
4
5
const CustomTextField: React.FC<Props> = ({ path }) => {
6
const { value, setValue } = useField<string>({ path })
7
8
return <input onChange={(e) => setValue(e.target.value)} value={value.path} />
9
}

The useField hook accepts an args object and sends back information and helpers for you to make use of:

1
const field = useField<string>({
2
path: 'fieldPathHere', // required
3
validate: myValidateFunc, // optional
4
disableFormData?: false, // if true, the field's data will be ignored
5
condition?: myConditionHere, // optional, used to skip validation if condition fails
6
})
7
8
// Here is what `useField` sends back
9
const {
10
showError, // whether or not the field should show as errored
11
errorMessage, // the error message to show, if showError
12
value, // the current value of the field from the form
13
formSubmitted, // if the form has been submitted
14
formProcessing, // if the form is currently processing
15
setValue, // method to set the field's value in form state
16
initialValue, // the initial value that the field mounted with
17
} = field;
18
19
// The rest of your component goes here

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

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

ActionDescription
ADD_ROWAdds a row of data (useful in array / block field data)
DUPLICATE_ROWDuplicates a row of data (useful in array / block field data)
MODIFY_CONDITIONUpdates a field's conditional logic result (true / false)
MOVE_ROWMoves a row of data (useful in array / block field data)
REMOVERemoves a field from form state
REMOVE_ROWRemoves a row of data from form state (useful in array / block field data)
REPLACE_STATECompletely replaces form state
UPDATEUpdate 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
fieldsDeprecated. This property cannot be relied on as up-to-date.
submitMethod to trigger the form to submit
dispatchFieldsDispatch actions to the form field state
validateFormTrigger a validation of the form state
createFormDataCreate a multipart/form-data object from the current form's state
disabledBoolean denoting whether or not the form is disabled
getFieldsGets all fields from state
getFieldGets a single field from state by path
getDataReturns the data stored in the form
getSiblingDataReturns form sibling data for the given field path
setModifiedSet the form\'s modified state
setProcessingSet the form\'s processing state
setSubmittedSet the form\'s submitted state
formRefThe ref from the form HTML element
resetMethod to reset the form to its initial state
addFieldRowMethod to add a row on an array or block field
removeFieldRowMethod to remove a row from an array or block field
replaceFieldRowMethod to replace a row from an array or block field

useCollapsible

The useCollapsible hook allows you to control parent collapsibles:

PropertyDescription
collapsedState of the collapsible. true if open, false if collapsed
isVisibleIf nested, determine if the nearest collapsible is visible. true if no parent is closed, false otherwise
toggleToggles the state of the nearest collapsible
withinCollapsibleDetermine when you are within another collaspible

Example:

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

useDocumentInfo

The useDocumentInfo hook provides lots of information about the document currently being edited, including the following:

PropertyDescription
collectionIf the doc is a collection, its collection config will be returned
globalIf the doc is a global, its global config will be returned
idIf the doc is a collection, its ID will be returned
preferencesKeyThe preferences key to use when interacting with document-level user preferences
versionsVersions of the current doc
unpublishedVersionsUnpublished versions of the current doc
publishedDocThe currently published version of the doc being edited
getVersionsMethod to trigger the retrieval of document versions
docPermissionsThe current documents permissions. Collection document permissions fallback when no id is present (i.e. on create)
getDocPermissionsMethod to trigger the retrieval of document level permissions

Example:

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

useLocale

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

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

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:

PropertyDescription
userThe currently logged in user
logOutA method to log out the currently logged in user
refreshCookieA method to trigger the silent refreshing of a user's auth token
setTokenSet the token of the user, to be decoded and used to reset the user and token in memory
tokenThe logged in user's token (useful for creating preview links, etc.)
refreshPermissionsLoad new permissions (useful when content that effects permissions has been changed)
permissionsThe permissions of the current user
1
import { useAuth } from 'payload/components/utilities'
2
import { User } from '../payload-types.ts'
3
4
const Greeting: React.FC = () => {
5
const { user } = useAuth<User>()
6
7
return <span>Hi, {user.email}!</span>
8
}

useConfig

Used to easily fetch the full Payload config.

1
import { useConfig } from 'payload/components/utilities'
2
3
const MyComponent: React.FC = () => {
4
const config = useConfig()
5
6
return <span>{config.serverURL}</span>
7
}

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
import { useEditDepth } from 'payload/components/utilities'
2
3
const MyComponent: React.FC = () => {
4
const editDepth = useEditDepth()
5
6
return <span>My component is {editDepth} levels deep</span>
7
}

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
import { useTheme } from 'payload/components/utilities'
2
3
const MyComponent: React.FC = () => {
4
const { autoMode, setTheme, theme } = useTheme()
5
6
return (
7
<>
8
<span>The current theme is {theme} and autoMode is {autoMode}</span>
9
<button
10
type="button"
11
onClick={() => setTheme(prev => prev === "light" ? "dark" : "light")}
12
>
13
Toggle theme
14
</button>
15
</>
16
)
17
}

useTableColumns

Returns methods to manipulate table columns

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

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:

PropertyDescription
mostRecentUpdateAn object containing the most recently updated document. It contains the entitySlug, id (if collection), and updatedAt properties
reportUpdateA method used to report updates to documents. It accepts the same arguments as the mostRecentUpdate property.

Example:

1
import { useDocumentEvents } from 'payload/components/hooks'
2
3
const ListenForUpdates: React.FC = () => {
4
const { mostRecentUpdate } = useDocumentEvents()
5
6
return (
7
<span>
8
{JSON.stringify(mostRecentUpdate)}
9
</span>
10
)
11
}
Next

Customizing CSS & SCSS