Customizing Reusable React-Select menu & options components.
In a couple react projects I have worked on at work, we used the react-select library for our select field dropdowns, mainly because it provides us with a pre-built dropdown component that is aesthetically pleasing, high performant and easy to integrate (or so I thought) across multiple applications.
However, I was recently tasked with placing a button to the bottom of the dropdown menu, which was supposed to be visible when the dropdown options are displayed. (see image below)
After a day & half of digging through Google, the official react-select-documentation, what seemed like a thousand codesandboxes, breaking my version of the project (I had to upgrade the react-select version and painfully make changes to each of the numerous dropdowns in the application) I was able to deliver the UI Designer’s expectation. Hence I deemed it fit to write an article that might save another Front-End engineer the stress of going through that process.
Prerequisites
In this article I will presume:
- You have a basic knowledge of React
- Your current version of react-select is from 2.0.0 upwards.
What we are building
We will be building a select component that includes a custom menu and option component using the react-select library.
Implementation
To start replicating the steps below, you can use a codesandbox or any editor of your choice and install create-react-app. If you’re just interested in only the codes and no extra talk, just fork this codesandbox or Github repo. I have also included links to them at the end of the article.
STEP 1: Add react-select as a dependency (npm install react-select
or yarn add react-select
)
STEP 2: Create a folder for your custom react-select component (for this article we will call it custom-select-menu). Include custom-select.jsx
, data.jsx
and index.css
files inside the folder.
STEP 3: Import React, react-select, index.css into your custom-select.jsx
file. For the react-select import, we would be destructing the components property on the Select object. (The component property is key to customizing any component exposed by the react-select library. See the replacing components documentation for more details).
STEP 4: Inside custom-select.jsx
Create a functional component named CustomSelect and render Select in the component.
STEP 5: Import the CustomSelect component into the component you want it in and render it. Here we would import it into App.js.
Right now, we see the select component rendered without any functionality because data has not been passed to it yet.
STEP 6: Create a file to hold our data. For this article, I have added a file named data.jsx
inside the custom-select-menu folder. Inside it is the stateOptions array below.
STEP 7: Feed react-select options property with some data to display. Because we want our component to be reusable, we will be passing the options property that is supplied by react-select as a prop, which we would reference in App.js.
Import the stateOptions array into app.js and pass it as the value for the data variable in state, then inside the render function destructure data from state and assign it as a value to the options prop.
Right now Our select component is functional and returns a drop-down list of the data in the stateOptions array.
STEP 8: To now customize the select component to how we want it to look and add a custom button at the bottom of the menu, we will create a functional menu component and pass it as a value to the components prop provided by react-select.
Things to note:
<compents.Menu {...props}>
is a way to tell the react-select library that we want to create a custom menu component and we need all the current props and state in the rendered Select component, hence the restructuring{...props}
of props.prop.children
renders the children of the menu component. In this case, the options are rendered. Just after props.children is the button we want to position at the bottom of the menu.selectProps
is a property on the props object that exposes all props (custom and in-built) you passed to react-select. In this case, it exposes the custom changeOptionsData props (which we will soon pass a function as it’s value) we passed to the select element.- To add more custom functionality to our Select component, we wrote a conditional statement that will display either a span element with the fetching data… text for when we want to mimic a network request or a div element that display the menu’s children.
STEP 9: Add some styles to improve our button display.
STEP 10: pass the fetchingdata & the button onClick handler (changeOptionsData) as props from CustomSelect component to their respective references in app.js.
STEP 11: For the onClick functionality, we want to display a different data set when we click our button. First, update our data.jsx
with the second data set below.
Second, we import updatedCountries variable into app.jsx, and finally, we write our onClick handler (which is called changeOptionsData).
This is the code in app.js right now
Inside the handler function, we have the following logic.
- We set the fetchingData props to true (this will display the Fetching data… text)
- use a setTimeout function to mimic a network request.
- Inside the setTimeout, we update the data variable in state and set the fetchigData property in state to false.
STEP 12: Include styles for our label & fetching classes inside index.css
Right now our Menu component is good to go. When we click the change data button, the fetching data… text pops up and after two seconds our data set is switched. If you’re still interested in more keeping reading to see how to create an Option component and use the selected value in the next steps.
STEP 13: Create a custom option component and pass it to the components prop. This is done pretty much the same way the menu component was created, rather we’re replacing the Menu property that is inside the component object (provided by react-select) with Option. Right now, our final react-custom.jsx
looks like this
I have decided not to do anything extra with the Option component. You can choose to add any functionality or styles you want to it.
STEP 14: Pass the onChange prop provided by react-select as a prop in CustomSelect component (I have already done so in the code snippet above) and pass the handleChange handler as a value to it in app.js.
The handleChange function grabs the selected option and set's it as a value for the selectedOption variable in the state.
STEP 15: Conditionally render the selected option inside a paragraph element that is placed above the Select element in app.js. Below is the final state of app.js.
And Voila!!! we’re done. Our custom react-select menu component is ready.
Go forth and customize any react-select component to your choice using the examples above.
You can fork the code from this codesandbox or Github repo. Also, drop your comments and questions in the comment box. I will reply to them as soon as I see them.