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

default discord avatar
remy_90last year

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)

  • AH!

    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
    remy_9012 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
    aaronksaunders7 months ago

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

  • default discord avatar
    remy_907 months ago

    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

Star on GitHub


Chat on Discord



Can't find what you're looking for?

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