hooks on { Select } from 'payload/components/forms'

default discord avatar
9 months ago

I have the following DOM element select:

<select title="select" value={selectedOption} onChange={(e) => handleChange(e, path)}>
    {options.map((option, index) => <option value={option}>{option}</option>)}

The above works as expected

I'm trying to use payload's Select, as referenced in the subject title. I imagine hooks is the way to manage state, as onChange isn't provided - but they aren't ever triggered?

<Select name='select' label="my select" options={options} hooks={{
    afterChange: [() => console.log('afterChange')],
    beforeChange: [() => console.log('beforeChange')],
    afterRead: [() => console.log('afterRead')],
    beforeValidate: [() => console.log('beforeValidate')],
  }} />

Am I missing something? I would like to set a default value from


and update the selected value onChange (as achieved in the first example)

  • discord user avatar
    Payload Team
    9 months ago


    I linked the wrong import path in our last discussion. 1 min

    Ok so you will want to import the Select component like so

    import SelectInput from 'payload/dist/admin/components/forms/field-types/Select/Input';

    (see the component here:



    This will give you the styled component - so it looks and feels like other payload select components.

    What you need to do is implement similar functionality seen in this file in your custom Field component:


    You can see how that file imports the

    <SelectInput />

    which is the one you will import, all of the state management (getting and setting options for your custom select) will live in a file that then passes props (onChange, value, options, etc) down to the SelectInput component.

    I hope this makes sense and steers you in the right direction!!

  • default discord avatar
    6 months ago

    Hi @jarrod_not

    jared , I'm back! Following your recommendation above I have the following:
      options={options.map(option => option...)}
      onChange={e => handlePrerequisiteChange(e, path)}

    The above doesn't persist between refreshes.

    The following sometimes works when another field is updated:
    ``html <select title='prerequisite' value={selectedOption} onChange={e => handlePrerequisiteChange(e, path)} > {options.map((option, index) => ( <option key={r-${index}} value={${option.question}


    }> {


    } </option> ))} </select> ``` * I'm still using


    , I can't see how to make use of


    (without violating react hook laws). How could I update each dropdown with useFields? My implementation is below * Changing an option in my select won't trigger the clean/dirty flag for saving/publishing changes but sometimes persists when other fields change Hopefully the content below will help paint a picture of what I'm working with and why I chose


    : ```typescript // fields param is from: // const { fields, dispatch } = useFormFields(([fields, dispatch]) => ({ fields, dispatch })) const generateOptions: (fields: any) => string[] = fields => { const numberOfPages = pageState.pages.value const questionCombination = [...Array(numberOfPages).keys()].flatMap(pageNo => getAnswerOptionsFromAnswerTypes( // checks if boolean/multiple choice, etc // assuming there is currently only one question and answer fields[


    ], ).map<ConditionalLogicOptions>(option => ({ question: fields[


    ].value, answer: fields[


    ]?.value || '', })), ) return questionCombination } ``` Here's a screenshot displaying the dropdown comprised of state from multiple fields. using


    for the


    triggers the clean/dirty flag for saving a draft/publishing and reloading sends it back to its previous value, so it's still not persisting Progress! I've used


    instead of

    useState` to set the selectedOption. That sorts out my clean/dirty and the reload.

    The only remaining issue is converting my un-styled select to your SelectInput. My select HTML is still as above. I'm getting page ids coming through for the dropdown when I use the following:

      options={options.map((option) => ({</option>)
        label: option,
        value: option
      onChange={e => handlePrerequisiteChange(e, path)}
  • default discord avatar
    last month

    i am heading down this journey now, do you have some source code you wouldnt mind sharing

  • default discord avatar
    last month

    Hey Aaron, I'm hoping to make this publicly available at some point soon, perhaps as a plugin? In the interim, it's currently baked into closed source code, will send a DM for the time being

Open the post
Continue the discussion in Discord
Like what we're doing?
Star us on GitHub!


Connect with the Payload Community on Discord



Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.