React Bootstrap Typeahead with Formik

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 with Formik in this post.
React Bootstrap Typeahead
This typeahead is a react component with Bootstrap style written in TypeScript (that I find most fits my project), and was inspired by Twitter's JavaScript library named 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.
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.
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. 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 hook. To get the Formik field assigned value when selecting items in the typeahead, we have to use a helper method setValue.
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 and Data React Bootstrap Typeahead.
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.
