In this article I will show you guys how you can create this multiple tags input using React.JS and a bit of CSS
Lets create a new react js project by running npx create-react-app myapp
Now to simplify things I am goin to delete all the files inside src folder except for App.js
and index.js
and create a style.css
file. So our folder structure should look like this
Great now let's also delete all the unnecessary codes from index.js
and App.js
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import "./style.css";
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// src/App.js
function App() {
return (
<div className="App">
<h2>Enter Some Tags ...</h2>
</div>
);
}
export default App;
And I am also goin to add these CSS styles in our src/index.js
*{
margin: 0;
padding: 0;
}
html, body{
height: 100%;
}
body{
display: flex;
justify-content: center;
align-items: center;
font-family: 'Courier New', Courier, monospace;
font-weight: bold;
}
.tags-input-container{
border: 2px solid #000;
padding: .5em;
border-radius: 3px;
width: min(80vw, 600px);
margin-top: 1em;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: .5em;
}
.tag-item{
background-color: rgb(218, 216, 216);
display: inline-block;
padding: .5em .75em;
border-radius: 20px;
}
.tag-item .close{
height: 20px;
width: 20px;
background-color: rgb(48, 48, 48);
color: #fff;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
margin-left: .5em;
font-size: 18px;
cursor: pointer;
}
.tags-input{
flex-grow: 1;
padding: .5em 0;
border: none;
outline: none;
}
If you want better explanation of the CSS you can watch this video of mine.
Okay now if we were to start our app by running npm start
it should look like this
Alright now lets create a folder inside src folder named components inside that we are going to create a component file called TagsInput.js
// src/components/TagsInput.js
function TagsInput(){
return (
<div className="tags-input-container">
<div className="tag-item">{/* One hardcoded tag for test */}
<span className="text">hello</span>
<span className="close">×</span>
</div>
<input type="text" className="tags-input" placeholder="Type somthing" />
</div>
)
}
export default TagsInput
Now we can import and use in our App.js
// src/App.js
import TagsInput from "./components/TagsInput"
function App() {
return (
<div className="App">
<h2>Enter Some Tags ...</h2>
<TagsInput />
</div>
);
}
export default App;
Great, but no instead of having a hardcoded tag like this, we want an array and we should loop over the array and show a tag for each element. So lets use useState to do that
// src/components/TagsInput.js
import { useState } from 'react'
function TagsInput(){
const [tags, setTags] = useState([
"HTML", "CSS", "JavaScript"
])
return (
<div className="tags-input-container">
{ tags.map((tag, index) => (
<div className="tag-item" key={index}>
<span className="text">{tag}</span>
<span className="close">×</span>
</div>
)) }
<input type="text" className="tags-input" placeholder="Type somthing" />
</div>
)
}
export default TagsInput
Okay now by default our array should be empty and when we type something in our input and press Enter a new item should be added in our tags state array. So lets create a function for that and add onKeyDown event listener to our input.
// src/components/TagsInput.js
import { useState } from 'react'
function TagsInput(){
const [tags, setTags] = useState([])
function handleKeyDown(e){
// If user did not press enter key, return
if(e.key !== 'Enter') return
// Get the value of the input
const value = e.target.value
// If the value is empty, return
if(!value.trim()) return
// Add the value to the tags array
setTags([...tags, value])
// Clear the input
e.target.value = ''
}
return (
<div className="tags-input-container">
{ tags.map((tag, index) => (
<div className="tag-item" key={index}>
<span className="text">{tag}</span>
<span className="close">×</span>
</div>
)) }
<input onKeyDown={handleKeyDown} type="text" className="tags-input" placeholder="Type somthing" />
</div>
)
}
export default TagsInput
And now finally when even user clicks on the
close(x) button of a tag the tag should be removed from our tags array. So lets create a function that take a index as its argument and removes the item at that index from our tags array. And add onClick listener to the close buttons.
// src/components/TagsInput.js
import { useState } from 'react'
function TagsInput(){
const [tags, setTags] = useState([])
function handleKeyDown(e){
if(e.key !== 'Enter') return
const value = e.target.value
if(!value.trim()) return
setTags([...tags, value])
e.target.value = ''
}
function removeTag(index){
setTags(tags.filter((el, i) => i !== index))
}
return (
<div className="tags-input-container">
{ tags.map((tag, index) => (
<div className="tag-item" key={index}>
<span className="text">{tag}</span>
<span className="close" onClick={() => removeTag(index)}>×</span>
</div>
)) }
<input onKeyDown={handleKeyDown} type="text" className="tags-input" placeholder="Type somthing" />
</div>
)
}
export default TagsInput
And that's all we have successfully create a tags input using React and Bit of JavaScript.
Found it helpful? By me a Coffee ☕
Make sure you checkout my other articles and YouTube channel