Customizing React-Select with TypeScript: A Developer’s Alchemy

If you're reading this article because you think customizing the react-select library with TypeScript is going to be a walk in the park—close this tab right now. After combing through the documentation, I, too, was under the impression that this would be a plug-and-play endeavor. Man, was I in for a surprise!
Still here? Cool, let's dive right in.
The Magic Behind React-Select
For those who don't know, react-select is a highly customizable replacement for the HTML <select> element. It works exceptionally well with React, providing numerous ways to style the dropdown and the options within.
How To Create Custom Options with HTML Templates
Before diving into the code, let's understand that react-select gives you a very nifty components prop. This allows you to override any part of the UI.
Here's a quick example:
import React from 'react';
import Select, { components } from 'react-select';
const CustomOption = (props: any) => (
<components.Option {...props}>
<div>
<strong>{props.data.label}</strong>
<small>{props.data.description}</small>
</div>
</components.Option>
);
export const MySelect = () => (
<Select
components={{ Option: CustomOption }}
options={[
{ label: 'Apple', value: 'apple', description: 'A red fruit' },
{ label: 'Banana', value: 'banana', description: 'A yellow fruit' }
]}
/>
);
If you want to add more finesse to your options, you can use the isDisabled, isFocused, isSelected props.
import React from 'react';
import Select, { components } from 'react-select';
const CustomOption = (props: any) => {
const { isDisabled, isFocused, isSelected } = props;
return (
<components.Option {...props}>
<div style={{ opacity: isDisabled ? 0.5 : 1 }}>
<strong>{props.data.label}</strong>
{ isSelected && <span> •</span> }
<small style={{ color: isFocused ? 'blue' : 'grey' }}>
{props.data.description}
</small>
</div>
</components.Option>
);
};
export const MySelect = () => (
<Select
components={{ Option: CustomOption }}
options={[
{ label: 'Apple', value: 'apple', description: 'A red fruit' },
{ label: 'Banana', value: 'banana', description: 'A yellow fruit' }
]}
/>
);
Now you can make that option look the way you want.
Styling the Menu and MenuList: Giving Your Dropdown Some Sass
So you know:
the menu: is essentially the container that wraps around all the options you see when the dropdown is activated. It is responsible for the placement, size, and other container-specific styling of the dropdown list. Customizing
menuwill affect the dropdown's outer box.the menuList: is a child component within the
menuand directly wraps around the individual option items. CustomizingmenuListwill affect the styling and layout of the options inside themenubut not the external container itself.
Think of menu as the outer shell and menuList as the inner lining. Any customization you apply to these components will alter how the dropdown appears and behaves when opened.
Customizing the style in react-select is made possible with the styles prop. You can easily change the border radius, color, and many other styles.
const customStyles = {
menu: (provided: any) => ({
...provided,
borderRadius: '0px',
backgroundColor: 'lightgray'
}),
menuList: (provided: any) => ({
...provided,
padding: '0px'
})
};
export const MyStyledSelect = () => (
<Select
styles={customStyles}
options={[
{ label: 'Apple', value: 'apple' },
{ label: 'Banana', value: 'banana' }
]}
/>
);
Just remember that some of the styles might need an !important next to them or else they won't show.
Let's Jazz Up That Input
The input box itself can also be styled, just like the menu and options. Simply target control in the styles prop.
const inputStyles = {
control: (provided: any) => ({
...provided,
borderRadius: '15px',
borderColor: '#3f51b5'
})
};
export const MyInputStyledSelect = () => (
<Select
styles={inputStyles}
options={[
{ label: 'Apple', value: 'apple' },
{ label: 'Banana', value: 'banana' }
]}
/>
);
Don't forget about the menuPosition
The menuPosition is another vital setting when you're customizing your dropdowns, and it's often mistaken for menuPlacement. While menuPlacement determines the location of the menu in terms of above or below the control, menuPosition goes further to dictate how the dropdown menu is positioned in the DOM.
Here are the options you can set for the menuPosition prop:
absolute: This is the default value. The menu is rendered within the DOM hierarchy of the control. It won't break out of a parent element withoverflow: hiddenset. So, if yourreact-selectcomponent is inside a container that hides overflow, the dropdown might not be displayed properly.fixed: The menu is rendered at the root level of the DOM hierarchy, so it's not constrained by a parent'soverflow: hiddenstyle. This setting allows the dropdown to break out of any containing element, ensuring visibility.
Here's how you'd set it in code:
import Select from 'react-select';
export const MyFixedMenuSelect = () => (
<Select
menuPosition="fixed"
options={[
{ label: 'Apple', value: 'apple' },
{ label: 'Banana', value: 'banana' }
]}
/>
);
In this example, by setting the menuPosition to "fixed", the dropdown will be appended to the root level of the DOM and will not be confined by a parent element with overflow: hidden.
Think of menuPosition as the setup for how your dropdown behaves in a broader context within the DOM, much like how middleware affects an entire application. It gives you the control to adapt your dropdown menu to various scenarios and layout constraints. Choose wisely based on your application's needs!
The Aha Moment
By now, you should be feeling pretty comfortable manipulating react-select with TypeScript.
The best part? You can have these complex styles and custom options up and running faster than you can say "JavaScript fatigue."
That’s all, folks.
Happy coding! 🚀



