# React Bootstrap Typeahead with Formik

[Typeahead](https://en.wikipedia.org/wiki/Typeahead) is a powerful feature that we need in the form for a better user experience. There are many available JavaScript libraries for creating a typeahead feature based on various themes such as Bootstrap, Material UI, and Tailwind CSS. But, I'll cover [React BootStrap Typeahead](https://github.com/ericgio/react-bootstrap-typeahead) with [Formik](https://formik.org/) in this post.

## React Bootstrap Typeahead

This typeahead is a react component with [Bootstrap](https://getbootstrap.com/) style written in TypeScript (that I find most fits my project), and was inspired by Twitter's JavaScript library named [`typeahead.js`](https://github.com/twitter/typeahead.js). It supports single-and-multiple-selection functions and customizations.

### Basic React Bootstrap Typeahead Component

Let's create a simple state selection typeahead. This example is a single selection typeahead.

```typescript
import React, { useState } from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import { Option } from 'react-bootstrap-typeahead/types/types';

const states = [
  'Alabama',
  'Alaska',
  'Arizona',
  'California',
  'Colorado',
  'Florida'
];

const StateTypeahead = () => {
  const [selectedStates, setSelectedStates] = useState<Option[]>([]);

  return (
    <Typeahead
      id="state-typeahead"
      onChange={(selected) => setSelectedStates(selected)}
      options={states}
      placeholder="Choose a state..."
      selected={selectedStates}
    >
    </Typeahead>
  );
};

export { StateTypeahead };
```

For more examples and choices, you can follow [live examples here](https://ericgio.github.io/react-bootstrap-typeahead/).

## Formik

Formik allows you to work with form elements in React with ease. It is very organized in terms of state, validation and errors, and form submission.

*I already shared a summary of* [*Formik on how to set initialValues from API*](https://sinn.hashnode.dev/formik-how-to-set-initialvalues-from-api)*. There you can find how to create a basic Formik form, which I will skip that part in here.*

## React Bootstrap Typeahead and Formik

This usage is to create a custom typeahead that interacts with a Formik field via [`useField`](https://formik.org/docs/api/useField) hook. To get the Formik field assigned value when selecting items in the typeahead, we have to use a helper method `setValue`.

```typescript
import React from 'react';
import { FormControl, FormControlProps } from 'react-bootstrap';
import { useField } from 'formik';
import { Typeahead } from 'react-bootstrap-typeahead';
import { useEffectOnce } from 'usehooks-ts';
import { Option } from 'react-bootstrap-typeahead/types/types';

export type FormikTypeaheadOption = Option;

export type FormikTypeaheadProps = FormControlProps & {
  name: string;
  options: FormikTypeaheadOption[];
  feedback?: string;
  labelKey?: string;
  defaultSelectedOptions?: FormikTypeaheadOption[];
};

const FormikTypeahead = ({ name, options, labelKey, placeholder, feedback, defaultSelectedOptions }: FormikTypeaheadProps) => {
  const [_, meta, helpers] = useField(name);
  const { error, touched } = meta;
  const isInvalid = touched && Boolean(error);
  const isValid = touched && !error;
  const className = isInvalid ? 'is-invalid' : 'is-valid';

  useEffectOnce(() => {
    setFormikFieldValue(defaultSelectedOptions ?? []);
  });

  const setFormikFieldValue = (selectedOption: FormikTypeaheadOption[]) => {
    const value = labelKey ? (selectedOption[0] as Record<string, string | number>)?.[labelKey] : selectedOption[0];

    if (value) {
      helpers.setValue(value);
    }
  };

  const handleChange = (selectedOption: FormikTypeaheadOption[]) => {
    setFormikFieldValue(selectedOption);
  };

  return (
    <>
      <Typeahead
        id={name}
        onChange={(selected) => handleChange(selected)}
        onInputChange={(text) => helpers.setValue(text)}
        onBlur={() => helpers.setTouched(true)}
        labelKey={labelKey}
        placeholder={placeholder}
        options={options}
        defaultSelected={defaultSelectedOptions ?? []}
        {...{ isInvalid, className, isValid }}
        inputProps={{ id: name }}
      />
      {feedback && <FormControl.Feedback type="valid">{feedback}</FormControl.Feedback>}
      {error && <FormControl.Feedback type="invalid">{error}</FormControl.Feedback>}
    </>
  );
};

export { FormikTypeahead };
```

So now we have the `FormikTypeahead` component and then we can use like control in Formik form.

To learn more about the snippet code above, I'd suggest you read [Rendering React Bootstrap Typeahead](https://github.com/ericgio/react-bootstrap-typeahead/blob/main/docs/Rendering.md) and [Data React Bootstrap Typeahead](https://github.com/ericgio/react-bootstrap-typeahead/blob/main/docs/Data.md).

## Conclusion

To offer the user the best experience in our form, Typeahead is a great choice. And, you can find many open-source JavaScript libraries to create it in your way. However, I've picked up React Bootstrap Typeahead alongside Formik for my current project.

Hopefully, this piece of post is helpful to you. If you have any comments, please do share.
