Build Multiselect component in few lines
Published: 2020-09-05 01:44:52

# **Introduction**

## What We Will Be Building

![React Multiselect](https://dev-to-uploads.s3.amazonaws.com/i/jdcmgz7keaa1m4a2r28p.gif)

In this example, i will show you how you can build sime  React Multiselect component. You can see basic logic behind component, and how you can use to build something simmilar yourself.

## What is multiselect

**React Multiselect** - is a component that allows users to tick multiple options. Its implementation is quite simple, and in exchange brings a lot of UX value.

## Prerequisites

- This tutorial assumes that you have working knowledge of React
- We are going to Use React Hooks
- For css library I used here [TailwindCSS](https://tailwindcss.com/), but you can use other if you like
- Before we get started, ensure that you have Node, Yarn, or npm installed in your environment.
- Have a Web browser ofcourse

# **Creating the React App**

Now that we have all the information we will need to connect our application and we know what are we building, let's start building out our application!

Open your **teminal**, once there, we are going to be using the `create-react-app` command to get our application running. Run the following command:

```
npx create-react-app multiselect
```

Now to explain a bit.

The `npx` command will install and run the command `create-react-app` for us. The last part of that command is the name of our app. We are going to be naming our app `multiselect`, feel free to name it whatever you want.

Once **cli** has finished creating the project folder you can cd into it, and run it:

```
cd multiselect
npm start
```

Open your brower in type into url -> `localhost:3000` to see our default React start page.

It will look like this:

![React Starter](https://dev-to-uploads.s3.amazonaws.com/i/nu1uuvuzrpurlhr53zq1.png)

# **Install TailwindCSS**

Next step is to install and configure tailwindcss. So I do not want to make this article too long, so you can check out these 2 guides on how to setup React with Tailwind:

[React & Tailwind Setup](https://dev.to/0x96f/react-and-tailwind-css-setup-51h0)
[Configure React with Tailwind](https://blog.logrocket.com/create-react-app-and-tailwindcss/)

Anyway If you do not want to use Tailwindcss, you can choose any other css framework (Bootstrap, Foundation etc), the code will work just fine.


# **Our Components**

We will need 2 files, for this one to hold **Multiselect** component & one to hold **Dropdown**.

Within the `/src` folder, create a folder named `/components`. With that folder, create three files:

- **./Multiselect.js**
- **./Dropdown.js**

## **Multiselect Component**

Now we will start working on MultiSelect component.
Open you Multiselect.js & paste following code inside it:

```
import React, { useState } from "react";

const MultiSelect = () => {
  const [items, setItems] = useState(["john", "milos", "steph", "kathreine"]);
  const [selectedItems, setSelected] = useState([]);

  return (
    <div className="autcomplete-wrapper">
      <div className="autcomplete">
        <div className="w-full flex flex-col items-center mx-auto">
          <div className="w-full">
            <div className="flex flex-col items-center relative">
              <div className="w-full ">
                <div className="my-2 p-1 flex border border-gray-200 bg-white rounded ">
                  <div className="flex flex-auto flex-wrap">
                    {selectedItems.map((tag, index) => {
                      return (
                        <div
                          key={index}
                          className="flex justify-center items-center m-1 font-medium py-1 px-2 bg-white rounded-full text-teal-700 bg-teal-100 border border-teal-300 "
                        >
                          <div className="text-xs font-normal leading-none max-w-full flex-initial">
                            {tag}
                          </div>
                          <div className="flex flex-auto flex-row-reverse">
                            <div>
                           
                            </div>
                          </div>
                        </div>
                      );
                    })}
                    <div className="flex-1">
                      <input
                        placeholder=""
                        className="bg-transparent p-1 px-2 appearance-none outline-none h-full w-full text-gray-800"
                      />
                    </div>
                  </div>
                  <div className="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200">
                    <button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
               
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default MultiSelect;
```

## **Adding Dropdown**

Let's build out our dropdown now. We need our dropdown to open options and allow users to add/remove tags. 

Now will introduce new Component `Dropdown.js`, do not forget to create it if you didn't already, and there put view of our dropdown

Also we will Updated **Multiselect component** with *showing/hidding* dropdown on click.

Here are our now our two updated components:

**Dropdown.js**

```  
import React from "react";  
  
const Dropdown = ({ list }) => {  
  return (  
    <div  
      id="dropdown"  
      className="absolute shadow top-100 bg-white z-40 w-full lef-0 rounded max-h-select overflow-y-auto "  
    >  
      <div className="flex flex-col w-full">  
        {list.map((item, key) => {  
          return (  
            <div  
              key={key}  
              className="cursor-pointer w-full border-gray-100 rounded-t border-b hover:bg-teal-100"  
            >  
              <div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-teal-100">  
                <div className="w-full items-center flex">  
                  <div className="mx-2 leading-6  ">{item}</div>  
                </div>  
              </div>  
            </div>  
          );  
        })}  
      </div>  
    </div>  
  );  
};  
  
export default Dropdown;  
```  

**Multiselect.js**

```
import React, { useState } from 'react';
// import dropdown component
import Dropdown from './Dropdown';


const Multiselect = () => {
    // state showing if dropdown is open or closed
    const [dropdown, setDropdown] = useState(false);
    // managing dropdown items (list of dropdown items)
    const [items, setItems] = useState(['john', 'milos', 'steph', 'kathreine']);
    // contains multiselect items
    const [selectedItems, setSelected] = useState([]);

    // toggle dropdown open/close  
    const toogleDropdown = () => {
        setDropdown(!dropdown)
    };

    return (<div className="autcomplete-wrapper">
        <div className="autcomplete">
        <div className="w-full flex flex-col items-center mx-auto">
    <div className="w-full">
        <div className="flex flex-col items-center relative">
            <div className="w-full ">
                <div className="my-2 p-1 flex border border-gray-200 bg-white rounded ">
                    <div className="flex flex-auto flex-wrap">
                        {
                            selectedItems.map((tag, index) => {
                                return (
                                    <div key={index} className="flex justify-center items-center m-1 font-medium py-1 px-2 bg-white rounded-full text-teal-700 bg-teal-100 border border-teal-300 ">
                                            <div className="text-xs font-normal leading-none max-w-full flex-initial">{ tag }</div>
                                            <div className="flex flex-auto flex-row-reverse">
                                                <div>
                                                    <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" 
                                                    className="feather feather-x cursor-pointer hover:text-teal-400 rounded-full w-4 h-4 ml-2">
                                                        <line x1="18" y1="6" x2="6" y2="18"></line>
                                                        <line x1="6" y1="6" x2="18" y2="18"></line>
                                                    </svg>
                                                </div>
                                            </div>
                                        </div>)
                            })
                        }
                        <div className="flex-1">
                            <input placeholder="" className="bg-transparent p-1 px-2 appearance-none outline-none h-full w-full text-gray-800"/>
                        </div>
                    </div>
                    <div className="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200" onClick={toogleDropdown}>
                        <button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
                            <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="feather feather-chevron-up w-4 h-4">
                                <polyline points="18 15 12 9 6 15"></polyline>
                            </svg>
                        </button>
                    </div>
                </div>
            </div>
        </div>
         { dropdown  ? <Dropdown list={items}></Dropdown>: null }
    </div>
</div>

    </div>
        </div>)
};

export default Multiselect;
```


> Notice what we changed We've added **dropdown component**, look at the bottom of **Multiselect** component and added state for dropdown and `toogleDropdown` method to to switch between open and close state using: `setDropdown(!dropdown)`.


## Adding Option to Add/Remove Tags

Now this is the last step, we can add 2 methods to add & remove tags to and from multiselect.

This will give us options to add item to multiselect by clicking on it from dropdown list, and remove it from multiselect by click on X.

Check Updated Component:

**Multiselect.js**

```
import React, { useState } from 'react';
import Dropdown from './Dropdown';


const Multiselect = () => {
    // state showing if dropdown is open or closed
    const [dropdown, setDropdown] = useState(false);
    // managing dropdown items (list of dropdown items)
    const [items, setItems] = useState(['john', 'milos', 'steph', 'kathreine']);
    // contains selected items
    const [selectedItems, setSelected] = useState([]);


    const toogleDropdown = () => {
        setDropdown(!dropdown)
    };
    // adds new item to multiselect 
    const addTag = (item) => {
        setSelected(selectedItems.concat(item));
        setDropdown(false);
    };
    // removes item from multiselect
    const removeTag = (item) => {
        const filtered = selectedItems.filter((e) => e !== item);
        setSelected(filtered);
    }

    return (<div className="autcomplete-wrapper">
        <div className="autcomplete">
        <div className="w-full flex flex-col items-center mx-auto">
    <div className="w-full">
        <div className="flex flex-col items-center relative">
            <div className="w-full ">
                <div className="my-2 p-1 flex border border-gray-200 bg-white rounded ">
                    <div className="flex flex-auto flex-wrap">
                        {
                            selectedItems.map((tag, index) => {
                                return (
                                    <div key={index} className="flex justify-center items-center m-1 font-medium py-1 px-2 bg-white rounded-full text-teal-700 bg-teal-100 border border-teal-300 ">
                                            <div className="text-xs font-normal leading-none max-w-full flex-initial">{ tag }</div>
                                            <div className="flex flex-auto flex-row-reverse">
                                                <div onClick={() => removeTag(tag)}>
                                                    <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" 
                                                    className="feather feather-x cursor-pointer hover:text-teal-400 rounded-full w-4 h-4 ml-2">
                                                        <line x1="18" y1="6" x2="6" y2="18"></line>
                                                        <line x1="6" y1="6" x2="18" y2="18"></line>
                                                    </svg>
                                                </div>
                                            </div>
                                        </div>)
                            })
                        }
                        <div className="flex-1">
                            <input placeholder="" className="bg-transparent p-1 px-2 appearance-none outline-none h-full w-full text-gray-800"/>
                        </div>
                    </div>
                    <div className="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200" onClick={toogleDropdown}>
                        <button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
                            <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="feather feather-chevron-up w-4 h-4">
                                <polyline points="18 15 12 9 6 15"></polyline>
                            </svg>
                        </button>
                    </div>
                </div>
            </div>
        </div>
         { dropdown  ? <Dropdown list={items} addItem={addTag}></Dropdown>: null }
    </div>
</div>

    </div>
        </div>)
};

export default Multiselect;
```

**Dropdown.js**

```
import React from 'react';


const Dropdown = ({list, addItem}) => {


    return (<div id="dropdown" className="absolute shadow top-100 bg-white z-40 w-full lef-0 rounded max-h-select overflow-y-auto ">
    <div className="flex flex-col w-full">
        { list.map((item, key) => {
            return <div key={key} 
            className="cursor-pointer w-full border-gray-100 rounded-t border-b hover:bg-teal-100" 
            onClick={() => addItem(item)}>
            <div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-teal-100" >
                <div className="w-full items-center flex">
        <   div className="mx-2 leading-6  ">
            { item }
           </div>
          </div>
         </div>
        </div>
        })}
    </div>
</div>);

};

export default Dropdown;
```

> What have we changed, nothing much, we added 2 new methods: `addTag`, `removeTag` in Multiselect, they will allow use to like their names say remove them and add them to multiselect

# **Conclusion**

While this is a very simple tutorial, it shows how far we can get with just few lines of react code (most of the code is css classes from tailwind). 

So what does this all mean? What have you learned? You learned how to create a React  multiselect component with all the basic functionality encapsulated within it. You also learned how to pass values to the component, and how to use useState hook.

Now don't just stare there go and try buiding something yourself, because that is the fastest way you will learn!

If you have any questions, please don’t hesitate to leave a **comment** below.

> If you liked this post, you can find more on:

> Following me on Twitter: