Create suggested search bar with React-Select
Here is an example of the search bar we will be making. We will be going through the set-up for react-select first and then style the search bar with emotion.js and react-select style keys.
1. Install react-select
npm install --save react-select
to check if the library has been successfully installed, check in the node_modules folder for react-select
. If it doesn’t come up, I normally just restart the computer and it’s there.
2. Importing react-select
import { Select } from 'react-select'
at the top of the file.
3. Make a search list
My search list in the example above is from a data in json format imported as projectList
mydata.json
is a one massive array containing objects with keys and values.
For our search list, we only want to extract the “project_name” to show up on the search list.
To make a search list, each object in the data must have at least 2 values: label
(a string) and value
(any type).
Importing projectList at the top along with all the other imports
import projectList from '../data/mydata.json'
To extract the label
and value
from projectlist.json, we can use JavaScript map()
method
const searchList = projectList.map(
({ project_name }) => {
return{
value: project_name,
label: project_name
}
}
);
4. Create class component for Search Bar
creating a class component for the search bar allows me to have a search bar as its own ‘component’, controlling its state
and render out react-select
class SearchBar extends React.Componenet{
state = {
selectedOption: null,
} handleChange = selectedOption => {
this.setState({ selectedOption })
// code to make something happen after selecting an option
} render(){
return ()
}
}
We set the initial state of the selectedOption
to be null
meaning that there’s no value in the beginning as we haven’t selected any option.
5. What goes inside the render() function
Inside the render()
function from a SearchBar class component we made above, we are going to be returning react-select
props
full react-select props documentation can be found here
These are the props i’ll be using:
value
— having this props will make the selected option appear in your search bar after clicking it
options
— this is probably what you need for your search bar to have the suggested drop-down menu
onChange
— this props takes in the function that you wrote to update the initial state. This function will depend on what you want the web to happen after an option is selected from a drop-down menu.
placeholder
— takes in the string that appears initially on the search bar before the user starts typing
openMenuOnClick
— prevents the option to reveal/open-up when the user clicks the search bar
Styling Props
style
— for custom styling the search bar
classNamePrefix
— for overriding react-select CSS className
Here is the example of what I pass through each prop. We will add the styling props to the return()
method after we style the search bar first.
return (
<div>
<Select
value={selectedOption}
options={searchList}
onChange={this.handleChange}
placeholder= "Search..."
openMenuOnClick={false}
/>
</div>
)
6. Styling Search Bar
There are many ways you can style it. I used both emotion.js and react-select style key.
Emotion.js
Emotion is a CSS in JavaScript style so it is very convenient to style a React Component without having a separate .css file
npm install --save @emotion
We will be importing @emotion/styled
instead because we are going to use the styled.div
style API for creating components.
import styled from '@emotion/styled'
The basic styling that we are going to change is the dimension of the search bar and the style of the vertical scroll bar
const StyledSearch = styled(Select)`
width: 300px;
padding: 20px;
.select__menu-list::-webkit-scrollbar{
width: 4px;
height: 0px;
}
.select__menu-list::-webkit-scrollbar-track{
background: #f1f1f1;
}
.select__menu-list::-webkit-scrollbar-thumb{
background: #888;
}
.select__menu-list::-webkit-scrollbar-thumb:hover{
background: #555;
}
`
StyledSearch
has to be capital letter because we are styling React Component
Notice className .select__menu-list
for styling the vertical scroll bar. This is because we are trying to override the react-select CSS className.
Since all the className starts with .select
we can give a classNamePrefix= "select"
in the return method.
Updating return( ) method for Emotion.js
return (
<div>
<Select
value={selectedOption}
options={searchList}
onChange={this.handleChange}
styles={customStyles}
placeholder= "Search..."
openMenuOnClick={false}
classNamePrefix= "select"
/>
</div>
)
further documentation on styling react-select with classname here
Style Key
The next part of styling uses style key (a little bit complex).
The key i’ll be using are:
control
— for styling the search box
option
— for styling the dropdown menu options (the searchList)
menu
— for styling the dropdown menu box
input
— what the user type into the search box
singleValue
— applies to the selected option that the user chooses
Here is the code sample:
Updating return( ) method for Style Key
We now need to put in the styles
props in the render()
method
return (
<div>
<Select
value={selectedOption}
options={searchList}
onChange={this.handleChange}
styles={customStyles}
placeholder= "Search..."
openMenuOnClick={false}
classNamePrefix= "select"
styles={customStyles}
/>
</div>
)
7. EXTRA: adding search icon
React-select comes with a dropdown indicator. If you want to change it to search-icon, you can!
First, install FortAwesome
npm install --save @fortawesome
Importing FontAwesome and its search icon
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'import { faSearch } from '@fortawesome/free-solid-svg-icons
In the render()
method just before the return()
statement, use a constant DropdownIndicator
to change its icon to search-icon
const DropdownIndicator = props => {
return(
components.DropdownIndicator && (
<components.DropdownIndicator {...props}>
<FontAwesomeIcon icon={faSearch} />
</components.DropdownIndicators>
)
)
}
Updating return( ) method for Search-Icon
use the components
props to pass down the DropdownIndicators
return (
<div>
<Select
value={selectedOption}
options={searchList}
onChange={this.handleChange}
styles={customStyles}
placeholder= "Search..."
openMenuOnClick={false}
classNamePrefix= "select"
styles={customStyles} components={ {DropdownIndicator} }
/>
</div>
)