When server rendering custom components within form state, those components receive a path that is correct at render time, but potentially stale after manipulating array and blocks rows. This causes the field to briefly render incorrect values while the form state request is in flight. The reason for this is that paths are passed as a prop statically into those components. Then when we manipulate rows, form state is modified, potentially changing field paths. The component's `path` prop, however, hasn't changed. This means it temporarily points to the wrong field in form state, rendering the data of another row until the server responds with a freshly rendered component. This is not an issue with default Payload fields as they are rendered on the client and can be passed dynamic props. This is only an issue within custom server components, including rich text fields which are treated as custom components. Since they are rendered on the server and passed to the client, props are inaccessible after render. The fix for this is to provide paths dynamically through context. This way as we make changes to form state, there is a mechanism in which server components can receive the updated path without waiting on its props to update.
94 lines
1.9 KiB
TypeScript
94 lines
1.9 KiB
TypeScript
import type { CollectionConfig } from 'payload'
|
|
|
|
export const postsSlug = 'posts'
|
|
|
|
export const PostsCollection: CollectionConfig = {
|
|
slug: postsSlug,
|
|
admin: {
|
|
useAsTitle: 'title',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'renderTracker',
|
|
type: 'text',
|
|
admin: {
|
|
components: {
|
|
Field: './collections/Posts/RenderTracker.js#RenderTracker',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'validateUsingEvent',
|
|
type: 'text',
|
|
admin: {
|
|
description:
|
|
'This field should only validate on submit. Try typing "Not allowed" and submitting the form.',
|
|
},
|
|
validate: (value, { event }) => {
|
|
if (event === 'onChange') {
|
|
return true
|
|
}
|
|
|
|
if (value === 'Not allowed') {
|
|
return 'This field has been validated only on submit'
|
|
}
|
|
|
|
return true
|
|
},
|
|
},
|
|
{
|
|
name: 'blocks',
|
|
type: 'blocks',
|
|
blocks: [
|
|
{
|
|
slug: 'text',
|
|
fields: [
|
|
{
|
|
name: 'text',
|
|
type: 'text',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
slug: 'number',
|
|
fields: [
|
|
{
|
|
name: 'number',
|
|
type: 'number',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'array',
|
|
type: 'array',
|
|
admin: {
|
|
components: {
|
|
RowLabel: './collections/Posts/ArrayRowLabel.js#ArrayRowLabel',
|
|
},
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'customTextField',
|
|
type: 'text',
|
|
defaultValue: 'This is a default value',
|
|
admin: {
|
|
components: {
|
|
Field: './collections/Posts/TextField.js#CustomTextField',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'defaultTextField',
|
|
type: 'text',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|