In most CMSs, hooks live on the whole document. In Payload, a hook lives on a specific field and receives that field's context — siblingData, value, operation:
{
name: 'slug',
type: 'text',
hooks: {
beforeChange: [
({ value, siblingData, operation }) => {
if (operation === 'create' && !value) {
return slugify(siblingData.title) // compute the slug from a sibling field
}
return value
},
],
},
}
Combine that with virtual: true and you get purely computed fields: the hook produces the value on afterRead, and nothing ever lands in the database.
It's a small shift in mental model, but it makes logic local to the data it touches instead of scattered across one giant document-level hook.
Top comments (0)