React-Tags

React-tags is a simple tagging component ready to drop in your React projects. The component is inspired by GMail's To field in the compose window.

demo

Features

  • Autocomplete based on a suggestion list
  • Keyboard friendly and mouse support
  • Reorder tags using drag and drop

Why

Because I was looking for an excuse to build a standalone component and publish it in the wild? To be honest, I needed a tagging component that provided the above features for my [React-Surveyman] project. Since I was unable to find one which met my requirements (and the fact that I generally enjoy re-inventing the wheel) this is what I came up with.

Installation

The preferred way of using the component is via NPM

npm install --save react-tag-input

It is, however, also available to be used separately (dist/ReactTags.min.js). If you prefer this method remember to include [ReactDND] as a dependancy.

Usage

Here's a sample implementation that initializes the component with a list of initial tags and suggestions list. Apart from this, there are multiple events, handlers for which need to be set. For more details, go through the [API].

import React from 'react';
import ReactDOM from 'react-dom';
import { WithContext as ReactTags } from 'react-tag-input';

class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            tags: [{ id: 1, text: "Thailand" }, { id: 2, text: "India" }],
            suggestions: ['USA', 'Germany', 'Austria', 'Costa Rica', 'Sri Lanka', 'Thailand']
        };
        this.handleDelete = this.handleDelete.bind(this);
        this.handleAddition = this.handleAddition.bind(this);
        this.handleDrag = this.handleDrag.bind(this);
    }

    handleDelete(i) {
        let tags = this.state.tags;
        tags.splice(i, 1);
        this.setState({tags: tags});
    }

    handleAddition(tag) {
        let tags = this.state.tags;
        tags.push({
            id: tags.length + 1,
            text: tag
        });
        this.setState({tags: tags});
    }

    handleDrag(tag, currPos, newPos) {
        let tags = this.state.tags;

        // mutate array
        tags.splice(currPos, 1);
        tags.splice(newPos, 0, tag);

        // re-render
        this.setState({ tags: tags });
    }

    render() {
        const { tags, suggestions } = this.state;
        return (
            <div>
                <ReactTags tags={tags}
                    suggestions={suggestions}
                    handleDelete={this.handleDelete}
                    handleAddition={this.handleAddition}
                    handleDrag={this.handleDrag} />
            </div>
        )
    }
};

ReactDOM.render(<App />, document.getElementById('app'));

A note about Contexts
One of the dependencies of this component is the [react-dnd] library. Since the 1.0 version, the original author has changed the API and requires the application using any draggable components to have a top-level [backend] context. So if you're using this component in an existing Application that uses React-DND you will already have a backend defined, in which case, you should require the component without the context.

const ReactTags = require('react-tag-input').WithOutContext;

Otherwise, you can simply import along with the backend itself (as shown above). If you have ideas to make this API better, I'd [love to hear].

GitHub