Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path from custom input component for field is incorrect in field nested inside block field #6571

Closed
cristobalbahe opened this issue May 30, 2024 · 4 comments
Assignees
Labels

Comments

@cristobalbahe
Copy link

cristobalbahe commented May 30, 2024

Link to reproduction

No response

Payload Version

3.0.0-beta.34

Node Version

20.6.0

Next.js Version

14.3.0-canary.68

Describe the Bug

Custom input component receives wrong path from props and it won't work when used inside useField()

Reproduction Steps

I don't know if this is specific to the beta version of Payload since I jumped straight to it never having used the 2.0 version, but I found an error when creating a custom field that has a custom input component.
I have the following schema for a field inside a collection called pages:

{
   name: 'layout',
   type: 'blocks',
   blocks: [
      {
         slug: 'text',
         fields: [
              {
                 name: 'colors',
                 type: 'group',
                 fields: [
                    {
                        name: 'textColor',
                        type: 'text',
                        required: true,
                        defaultValue: '#000000',
                        admin: {
                          width: '50%',
                          components: {
                            Field: ColorsFieldInput,
                          },
                        },
                     },
                     {
                        name: 'text',
                        type: 'richText'
                     }
                 ]
              }
         ]
      }
   ]
} 

And this is my component ColorsFieldInput.tsx:

'use client'
import React from 'react'

import { TextInputProps } from '@payloadcms/ui/fields/Text'
import { useField } from '@payloadcms/ui/forms/useField'
import { FieldLabel } from '@payloadcms/ui/forms/FieldLabel'

const baseClass = 'custom-color-picker'

export const ColorsFieldInput: React.FC<TextInputProps> = (props) => {
  const { path, label, required } = props
  const field = useField<string>({})
  const { value, setValue, initialValue } = field
  return (
    <div className={baseClass}>
      <FieldLabel htmlFor={path} label={label} required={required} />
      <input
        type="color"
        value={value ?? initialValue}
        onChange={(e) => {
          setValue(e.target.value)
        }}
      />
    </div>
  )
}

If I try to pass path from props to useField(), the changed value wont persist because the path from props is not correct.
I noticed the path from props is different from the one I get if I leave path empty (If you do not provide a path or a name, this hook will look for one using the useFieldPath hook.)

From props I get: layout.text.colors.textColor

From useField() I get: layout.0.colors.textColor

Whenever I leave path empy in useField() it will persist the changes as it seems it's the correct path.

Adapters and Plugins

db-postgres

EDIT
I noticed that if this same field is nested inside a row field which shouldn't change the schema of path, I also get the correct result from getField() when I do not pass a path, but in the path from props, I get an extra dot where the field row would be in case it was another type of field, like the following: layout.text.colors..textColor

@cristobalbahe cristobalbahe added status: needs-triage Possible bug which hasn't been reproduced yet v3 labels May 30, 2024
@AthulPM97
Copy link

Any solution to this yet??

@rodrigo-mahamud
Copy link

Same problem here, when you click on publish changes the value does not persist.

@DanRibbens DanRibbens added status: assigned and removed status: needs-triage Possible bug which hasn't been reproduced yet labels Jun 9, 2024
@paulpopus
Copy link
Contributor

Hey the solution is to use useFieldProps to get the path instead when dealing with arrays/blocks etc.

import { useFieldProps } from '@payloadcms/ui/forms/FieldPropsProvider'
// ...
const { path } = useFieldProps()
const { value, setValue } = useField<string>({ path })

The reason being on the server side we can't know exactly where your data will end up, so client hooks are safer to retrieve the path as it can change dynamically as well, eg. if you drag the blocks around.

We will make sure this is properly documented.

Copy link

github-actions bot commented Sep 7, 2024

This issue has been automatically locked.
Please open a new issue if this issue persists with any additional detail.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants