Create a tags input component in ReactJs
Tags: react, design, tutorial
Published: 2019-07-11 10:58:04

![Tags Input Demo](https://thepracticaldev.s3.amazonaws.com/i/cltf78wmensp4vfwluvf.gif "Tags Input Demo")

## Project Setup
We are going to be building the component using ReactJs. Let's start by installing the essentials. First we're going to create a react app using React's [CRA](https://github.com/facebook/create-react-app "Create React App") or you can use any starter kit to begin with. Let's setup our `React` app.

```bash
npx create-react-app tags-input
cd tags-input
```
## Let's get started!
In the `index.js` file we're going to write the code for our base component `App`, you can name it anything you'd like.

```jsx
// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./styles.scss";

const App = () => {
	return (
		<div className="App">
			<span>Hello World!</span>
		</div>
	);
};

ReactDOM.render(<App />, document.getElementById("root"));
```

## Tags Input Component

We're going to be using functional components and React's `useState` hook to make it stateful.

```jsx
// TagsInput.jsx
import React from "react";
const TagsInput = () => {
	const [tags, setTags] = React.useState([]);
	return (
		<div className="tags-input">
			<ul>
				{tags.map((tag, index) => (
					<li key={index}>
						<span>{tag}</span>
						<i className="material-icons">close</i>
					</li>
				))}
			</ul>
			<input
				type="text"
				placeholder="Press enter to add tags"
			/>
		</div>
	);
};
export default TagsInput;
```

Since we are going to be storing an array of tags in the state, so we can initialize it as empty array. `useState` hook return two values i.e the current state( and a function that can used to update the state. We're using array destructuring to get both the values from the `useState`. The current state in our case is called `tags` and the function to update it is called `setTags`.

Then within the return function we're mapping the `tags` array and displaying all the tags that will be added by the user in the state. 

## Add tags functionality
Let's create the functionality to add tags. We're going add an event handler `onKeyUp` to our `input` tag and return a function called `addTags()` and pass in the `event` as an argument.

```jsx
// TagsInput.jsx
...
<input
    type="text"
    onKeyUp={event => addTags(event)}
    placeholder="Press enter to add tags"
/>
...
```

Next we'll define the `addTags()` function above `return` in our component.

```jsx
// TagsInput.jsx
import React from "react";
const TagsInput = () => {
	const [tags, setTags] = React.useState([]);
	const addTags = event => {
		if (event.key === "Enter" && event.target.value !== "") {
			setTags([...tags, event.target.value]);
			event.target.value = "";
		}
    };
    return (
    ...
    );
};
```

We can use keycodes to make sure that the tags are only added to state if the user has pressed `Enter` key. Alongside that we're also adding one more condition which is to prevent empty tags from being added to the state.

Then withing our `if` condition, if it's true we can add the tag entered by the user using our `setTags()` function. you'll notice that I'm using the spread operator(`...tags`) here to to first add the tags we already have and then add on the tag the user just entered. This syntax just makes sure that incoming tags are added in the last of the tags array and finally we're clearing out the value from our input tag so the user can enter the new one.

## Remove tags functionality

To remove a tag, the user can click on the close icon that all the tags have. I'm passing a `onClick` event handler to handle the remove tag functionality.

```jsx
// TagsInput.jsx
...
{tags.map((tag, index) => (
    <li key={index}>
        <span>{tag}</span>
        <i
            className="material-icons"
            onClick={() => removeTags(index)} 
        >
            close
        </i>
    </li>
))}
...
```

We're returning a `removeTags()` when the user click on close icon and passing the `index` of the tag that's been clicked to remove. Now right below our `addTags()`, we'll add `removeTags()`.

```jsx
// TagsInput.jsx
...
const addTags = event => {
    ...
};
const removeTags = index => {
    setTags([...tags.filter(tag => tags.indexOf(tag) !== index)]);
};
...
```

Since we're passing the `index` of the tag that the user wants to remove, we can use `filter()` method to remove the tag based on it's index. On the line no. 8 in above code, we're simply iterating our tags array and looking for a tag whose index matches the index of the tag the user wants to remove, once it's found it'll be filtered out and rest of the tags will remain in the resulting array. Finally we're using the spread operator again to pass in the resulting tags in an array and then use `setTags()` to update the state.

## Let's Import TagsInput component into our base component

```jsx
// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./styles.scss";

import TagsInput from './TagsInput';

const App = () => {
	return (
		<div className="App">
			<TagsInput />
		</div>
	);
};

ReactDOM.render(<App />, document.getElementById("root"));
```

Now how do we get the tags that the user added into our base component. We'll declare a function called `selectedTags` in our base component that we'll pass as props to our `TagsInput` component.

```jsx
...
const App = () => {
    const selectedTags = tags => console.log(tags)};
	return (
		<div className="App">
			<TagsInput selectedTags={selectedTags}/>
		</div>
	);
};
...
```

From our `TagsInput` component, we can now call the `selectedTags` method and pass the tags array to our base component.

```jsx
// TagsInput.jsx
...
const TagsInput = props => {
	const [tags, setTags] = React.useState([]);
	const addTags = event => {
		if (event.key === "Enter" && event.target.value !== "") {
            setTags([...tags, event.target.value]);
            props.selectedTags([...tags, event.target.value]);
			event.target.value = "";
		}
    };
    ...
};
```

You'll notice that we've passed `props` as parameter to our `TagsInput` component. We'll be using it to access the `selectedTags()` that we passed from the base component. On line no. 9 in above code, We're calling the `selectedTags()` method and passing in the same arguments as the `setTags` on line no. 8. Notice that I'm not passing the `tags` itself that we destructured from `useState` to avoid passing the older tags array.

Now whenever the user add a new tag, the base component will have the access to update tags array.

## Codepen Demo
{% codepen https://codepen.io/prvnbist/pen/jJzROe/ %}
Thanks for reading, this is my first blogpost here - any feedback is most welcome!(https://www.prvnbist.com/blog/create-a-tags-input-component-in-react)!