Skip to content

Instantly share code, notes, and snippets.

@hubgit
Last active March 31, 2025 22:59
Show Gist options
  • Save hubgit/e394e9be07d95cd5e774989178139ae8 to your computer and use it in GitHub Desktop.
Save hubgit/e394e9be07d95cd5e774989178139ae8 to your computer and use it in GitHub Desktop.
Use react-select with Formik
const options = [
{ value: 'foo', label: 'Foo' },
{ value: 'bar', label: 'Bar' },
]
return <Field name={'example'} component={SelectField} options={options} />
import { FieldProps } from 'formik'
import React from 'react'
import Select, { Option, ReactSelectProps } from 'react-select'
export const SelectField: React.SFC<ReactSelectProps & FieldProps> = ({
options,
field,
form,
}) => (
<Select
options={options}
name={field.name}
value={options ? options.find(option => option.value === field.value) : ''}
onChange={(option: Option) => form.setFieldValue(field.name, option.value)}
onBlur={field.onBlur}
/>
)
@ken-muturi
Copy link

ken-muturi commented Apr 16, 2023

Updated above with couple typing and import fixes

import {FieldProps} from "formik";
import React from "react";
import Select, {OptionsType, ValueType} from "react-select";

interface Option {
    label: string;
    value: string;
}

interface FormikSelectProps extends FieldProps {
    options: OptionsType<Option>;
    isMulti?: boolean;
}

export const FormikSelect =
    ({
         field,
         form,
         options,
         isMulti = false,
     }: FormikSelectProps) => {
        const onChange = (option: ValueType<Option | Option[], boolean>) => {
            form.setFieldValue(
                field.name,
                isMulti
                    ? (option as Option[]).map((item: Option) => item.value)
                    : (option as Option).value
            );
        };

        const getValue = () => {
            if (options) {
                return isMulti
                    ? options.filter(option => field.value.indexOf(option.value) >= 0)
                    : options.find(option => option.value === field.value);
            } else {
                return isMulti ? [] : ("" as any);
            }
        };

        return (
            <Select
                name={field.name}
                value={getValue()}
                onChange={onChange}
                options={options}
                isMulti={isMulti}
            />
        );
    };

I am having issues with my form using this custom component. The values are not added to formik field values. To explain in detail, I have a select which change, determines the values to pre-select on my custom react-select input (note values here not options). This also cascades this down to a 3rd input. These is a cascading inputs seem to be getting the values, however, the this values are on in the field value object. Please note that because this is a dynamic input am not able to use initialValues object. So i somewhat use the formik props to get the selected values and cascade down. see screenshots below

image

image

image

@alexluongfm
Copy link

React select (single select) that uses more of the formik hooks to reduce props passing and keep everything as simple as possible. Must be under the <Formik>/<Form> code to ensure hooks all work properly.

import React from 'react';
import Select, { Options } from 'react-select';
import { useField } from 'formik';

type Props = {
  selectOptions: Options[],
  formikFieldName: string,
  placeholder?: string,
};

/**
 * React Select but hooked into Formik
 * @returns {JSX.Element}
 * @constructor
 */
const FormikSelect = ({
  selectOptions,
  formikFieldName,
  placeholder,
}: Props) => {
  // eslint-disable-next-line no-unused-vars
  const [field, _, helpers] = useField(formikFieldName);
  const { setValue } = helpers;

  return (
    <Select
      defaultValue={selectOptions.find(
        (option) => option.value === field.value
      )}
      options={selectOptions}
      placeholder={placeholder}
      onBlur={field.onBlur}
      onChange={(option) => setValue(option.value)}
    />
  );
};

FormikSelect.defaultProps = {
  placeholder: '',
};

export default FormikSelect;

Example usage

        <FormikSelect
          selectOptions={[
            { value: 'foo', label: 'Foo' },
            { value: 'bar', label: 'Bar' },
          ]}
          formikFieldName="formikInitVals.shippingMethods"
          placeholder="Shipping Methods"
        />

Versions

formik: 2.4
react: 18.2

@rever96
Copy link

rever96 commented Aug 11, 2023

@alexluongfm with your versions still gives Generic type 'Options' requires 1 type argument(s). error on line 6

"react-select": "^5.7.4",

@IlyaZha
Copy link

IlyaZha commented Sep 22, 2023

My Solution for react-select@^5.7.4:

export default function MultipleSelect({ fieldName, placeholder, ...props }) {
  const [field, meta, { setValue }] = useField(fieldName);
  const options = props.children.map((option) => ({
    value: option.props.value,
    label: option.props.children,
  }));

  const onChange = (selectedOptions: MultiValue<any>) => {
    setValue(selectedOptions);
  }

  return (<>
    <Select
      isMulti={true}
      defaultValue={options.find((option) => option.value === field.value)}
      placeholder={placeholder}
      onChange={onChange}
      options={options}
      onBlur={field.onBlur}
    />
  </>);
}

Form of select should be wrapped with <Formik></Formik>

@shavonn
Copy link

shavonn commented Oct 14, 2024

I just did this...
onValueChange={(val) => formik.setFieldValue('timezone', val)}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment