Building a Comment Form with React-Mentions
Published: 2023-07-01 00:11:29

by [Sam Victor](https://blog.openreplay.com/authors/sam-victor)

<blockquote><em>A comment form is a user interface element that allows users to leave comments or messages on a particular thread or discussion, which typically includes a text box where users can enter their comments and other optional fields such as name, email, and website, and also include features such as @mentions, formatting options, and the ability to upload images or files. This article will show you how to use the React-mentions library to build a powerful comment form.</em></blockquote>






Before the introduction of `@mentions` in most applications, commenting on threads and messages felt like an isolated activity. In conversations with multiple participants, determining who a note was intended for required much work. There was no easy way to involve individuals not already part of the discussion, which often led to confusion, miscommunication, and limited engagement. However, with `@mentions` this problem has been addressed, and commenting on threads and messages has become more inclusive and engaging, allowing you to direct messages to specific individuals or groups, ensuring that the intended recipient receives your message. Moreover, by mentioning friends or experts, you can invite them to join the conversation and share their insights and opinions.

React Mentions is a library for building interactive mentions or tagging functionality in React applications. It allows users to mention or tag other users in a comment, message, or post by typing the ‘@’ symbol followed by the user’s name. The library provides auto-complete suggestions, customizable styles, and callbacks for handling user interactions. In this context, exploring React Mentions functionalities refers to learning about the different features and capabilities of the library and how to use them effectively in your React projects.

This tutorial explores the @mention functionally using the [React-mentions](https://www.npmjs.com/package/react-mentions) package.


## Scaffolding the Application

Let’s begin with creating our React project using Vite. Run the command below to scaffold a react project.

```
yarn create vite
```
 
 After setting up your react project, change the directory to the project and add the [React-Mentions](https://www.npmjs.com/package/react-mentions) plugin using the command below.
 
```
yarn add react-mentions
```

## Overview 

Before we dive into each of the functionalities, let’s get an overview and structure of the React Mentions component.

```jsx

const [result, setResult] = useState("");

const data = [
  {
    id: "Avatar",
    display: "Avatar Aang",
  },
  {
    id: "Spiderman",
    display: "Peter Parker",
  },
];

<MentionsInput value={result} onChange={(e) => setValue(e.target.value)}>
  <Mention style={mentionStyle} data={data} />
</MentionsInput>;
```

This code above shows the skeleton of the React-Mentions component, and it renders a mention input field that allows users to mention other users by typing “@” followed by their names. The `MentionsInput` component has a single child Mention component. The `value` prop controls the input field’s value, and the `onChange` prop handles changes to the input field value, updating the `result` variable.
The `Mention` component defines how mentions of users will be rendered in the input field, which leverages the `data` prop that provides the list of mentionable users. The `style` prop specifies the styling of the Mention component, which displays the user’s name or email address, especially when mentioned in the input field. 

Running the code above will give us the results below.

![-](https://blog.openreplay.com/images/building-a-comment-form-with-react-mentions/images/s_3AB75596E32609F9CCC4A2A1E17BAABFCECBC8D11BB2CA0CEF7A0C9709F968A2_1679152184744_ezgif.com-video-to-gif.gif)

### Styling and Customizing Mention Components.

From our previous example above, our user interface wasn’t looking good because it lacked a bit of style and customization. Let’s fix this by providing the necessary style for our React Mention components.

The React Mention library provides a style structure for the MentionInput and Mention components. This style is customizable to suit the user’s preference. Let’s put this into practice, create a `styles.module.css` file in the `src/` folder and paste the code below into it.

```css

/* mentions */
.mentions {
  margin: 2em 0;
}
.mentions--singleLine .mentions__control {
  display: inline-block;
  padding-left: 10px;
}
.mentions--singleLine .mentions__highlighter {
  padding: 1px;
  border: 2px inset transparent;
}
.mentions--singleLine .mentions__input {
  border: 2px inset grey;
  font-style: italic;
  padding-left: 10px;
}

.mentions--multiLine .mentions__control {
  font-family: monospace;
  font-size: 16pt;
}
.mentions--multiLine .mentions__highlighter {
  border: 1px solid transparent;
  padding: 9px;
  min-height: 63px;
}
.mentions--multiLine .mentions__input {
  border: 1px solid silver;
  padding: 9px;
  outline: 0;
  font-style: italic;
}
.mentions__suggestions__list {
  background-color: white;
  border: 1px solid rgba(0, 0, 0, 0.15);
  font-size: 10pt;
}
.mentions__suggestions__item {
  padding: 5px 15px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.15);
}
.mentions__suggestions__item--focused {
  background-color: #639551fe;
  color: #fff;
}
.mentions__mention {
  position: relative;
  z-index: 1;
  color: green;
  font-style: italic;
  text-shadow: 1px 1px 1px white, 1px -1px 1px white, -1px 1px 1px white,
    -1px -1px 1px white;
  text-decoration: none;
  pointer-events: none;
}
```

## Exploring React-Mentions Functionalities
Finally, let's explore the React Mention functionality and see what it offers. The React Mentions library has many explorable features useful when using the @mention functionality. Let’s get to use a few in this section.


### Single Line Input
The SingleLine Input functionality provides the user with a single-line text input field with the React mention style and functionalities. To create this, head to the `src/` folder and create an `Example.jsx` file in it. 


```jsx
import { useState } from "react";
import { Mention, MentionsInput } from "react-mentions";
import style from "./style.module.css";

const MentionExample = () => {
  const [result, setResult] = useState("");

  const data = [
    {
      id: "Ichigo",
      display: "Kurosaki Ichigo",
    },
    {
      id: "Madara",
      display: "Madara Uchiha",
    },
    {
      id: "Nobody",
      display: "nobody@someone.whoknows",
    },
    {
      id: "Iamvictorsam",
      display: "iamvictorsam@gmail.com",
    },
  ];

  return (
    <>
      <h1>Single Line Input</h1>
      <MentionsInput
        classNames={style}
        singleLine
        value={result}
        onChange={(e) => setResult(e.target.value)}
      >
        <Mention className={style.mentions__mention} data={data} />
      </MentionsInput>
    </>
  );
};

export default MentionExample;

```

In the code block above, we’re leveraging on the React-Mention components by providing them with the value of the result. The `classNames` prop is an object that specifies CSS classes for various components of the `MentionsInput`, while the value prop sets the `value` of the input field.

The `useState` hook is used to manage the state of the `result` variable, which stores the input field’s current value. The setResult function updates the state of the `result` variable whenever the input field value changes.
Finally, the `onChange` event handler is attached to the `MentionsInput` component, which calls the `setResult` function whenever the input field value changes.

We have also added the `singleLine` flag to the `MentionsInput` component to give us access to the single-line style from our custom mention style.

![-](https://blog.openreplay.com/images/building-a-comment-form-with-react-mentions/images/s_3AB75596E32609F9CCC4A2A1E17BAABFCECBC8D11BB2CA0CEF7A0C9709F968A2_1682319695234_ezgif.com-video-to-gif.gif)


### Multiline input 
Unlike the Single-line input, the Multi-Line input creates a bigger text field, like a text area, enabling users to enter texts and comment in multiple lines. This can be achieved by removing the single line flag thus, setting it to false. 

```jsx
return (
  <>
    <h1>Multi Line Input</h1>
    <MentionsInput
      classNames={style}
      value={result}
      onChange={(e) => setResult(e.target.value)}
    >
      <Mention className={style.mentions__mention} data={data} />
    </MentionsInput>
  </>
);

```

![-](https://blog.openreplay.com/images/building-a-comment-form-with-react-mentions/images/s_3AB75596E32609F9CCC4A2A1E17BAABFCECBC8D11BB2CA0CEF7A0C9709F968A2_1682320500507_ezgif.com-video-to-gif+3.gif)


### Using Multiple Triggers
The React Mention library also provides the flexibility of using and adding as many trigger methods of your choice. This section adds two more trigger methods to our default trigger (the @ symbol). This includes the `:site` and `?email` keywords. 

```jsx
  return (
    <>
      <h1>Multiple mention Trigger Method</h1>
      <MentionsInput
        classNames={style}
        value={result}
        onChange={(e) => setResult(e.target.value)}
      >
        <Mention className={style.mentions__mention} data={data} />
        <Mention className={style.mentions__mention} data={data} trigger={":site"} />
        <Mention className={style.mentions__mention} data={data} trigger={"?email"} />
      </MentionsInput>
    </>
  );
```

In the code block above, we added two more Mention components with the trigger property into the MentionInput component. We added the `:site` and `?email` keywords for both components newly added as triggers.

![-](https://blog.openreplay.com/images/building-a-comment-form-with-react-mentions/images/s_3AB75596E32609F9CCC4A2A1E17BAABFCECBC8D11BB2CA0CEF7A0C9709F968A2_1682321464028_ezgif.com-video-to-gif+4.gif)


### Fetching responses from external sources

Fetching responses from external sources takes our @mention form to the next level by allowing us to tap into vast databases and global sources for dynamic data retrieval. Whether fetching user information, live updates, or the latest trending tags, this feature empowers our form to stay up-to-date and deliver a seamless user experience. In this section, we’ll look at how to fetch data from an API and use it in our Mention form.

Firstly, let’s create some states and also handle our text input.

```jsx
const [text, setText] = useState("");
const [dataResp, setDataResp] = useState([]);

const handleInputChange = (event) => {
  setText(event.target.value);
};
```

Next, we’ll fetch the data from the URL and store it in the dataResp state we created earlier.

```jsx
useEffect(() => {
  fetch(
    "https://raw.githubusercontent.com/iamVictorSam/react-mentions-with-form/7d03dd94f7ae1740e835bef959d704ca81d1355b/src/names.json"
  )
    .then((response) => response.json())
    .then((json) => {
      const mentionableNames = json.people.map((person) => ({
        id: person.name,
        display: person.name,
      }));
      setDataResp(mentionableNames);
    })
    .catch((error) => console.log(error));
}, []);
```

Finally, we’ll inject our data into the Mention component to gain access to the names from the endpoint.

```jsx
return (
  <div>
    <h1>Fetching Mention Data From External Source</h1>
    <MentionsInput value={text} onChange={handleInputChange} classNames={style}>
      <Mention
        className={style.mentions__mention}
        trigger="@"
        data={dataResp}
        displayTransform={(id, display) => `@${display}`}
      />
    </MentionsInput>
    <div>{text}</div>
  </div>
);
```

We’ve used the `useEffect` hook from the code blocks above to fetch data from a JSON file containing names. The fetched JSON data is transformed into a format suitable for the mentioned component (`Mention` component) by mapping the names to an array of objects with `id` and `display` properties. The transformed data is stored in the `dataResp` state variable.

![-](https://blog.openreplay.com/images/building-a-comment-form-with-react-mentions/images/s_3AB75596E32609F9CCC4A2A1E17BAABFCECBC8D11BB2CA0CEF7A0C9709F968A2_1685894031457_ezgif.com-video-to-gif.gif)


<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>





## Building a Comment Form with React Mentions Functionalities

Let’s put the functionalities discussed above into a Comment Form. To start, create a `commentFormStyle.module.css` file in the `src/` folder and paste the styles below.

```css

.container {
  max-width: 500px;
  margin: 0 auto;
}
.form_group {
  margin-bottom: 20px;
}
.label {
  display: block;
  font-weight: bold;
  margin-bottom: 5px;
}
.input {
  width: 100%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.comment-input {
  width: 100%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
.submit-btn {
  padding: 10px 20px;
  background-color: #4caf50;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.commentTile {
  background-color: #000;
  color: #fff;
  padding: 10px;
  border-radius: 8px;
  margin: 20px auto;
  max-width: 500px;
}

```

We’ll be using the code above to style our Comment Form.


Next, paste the imports below into a `Form.jsx` file in the `src/` folder.

```jsx

import React, { useState, useEffect } from "react";
import { MentionsInput, Mention } from "react-mentions";
import styles from "./commentFormStyle.module.css";
import mentionStyle from "./style.module.css";
```

We’re importing our `Mention` components, styles, and some React states in the code above.
 
Next, We’ll be creating our custom Form components. Copy and paste the code after the imports in the `Form.jsx` file.
 
```jsx
const CommentForm = () => {
  //Declaring states
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [comment, setComment] = useState("");
  const [dataResp, setDataResp] = useState([]);
  const [submittedComment, setSubmittedComment] = useState(null);

  //handing our Submit
  const handleSubmit = (event) => {
    event.preventDefault();
    const randomId = Math.floor(Math.random() * 10000000);
    const currentDate = new Date().toLocaleString();
    const platform = getPlatform();
    const newComment = {
      id: randomId,
      name,
      email,
      comment,
      date: currentDate,
      platform,
    };
    setSubmittedComment(newComment);
    clearForm();
  };

  // Clearing Form State
  const clearForm = () => {
    setName("");
    setEmail("");
    setComment("");
  };

  // Getting user's Form State
  const getPlatform = () => {
    const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
    const isTablet = /(iPad|Android)/i.test(navigator.userAgent);
    if (isMobile) {
      return "Mobile";
    } else if (isTablet) {
      return "Tablet";
    } else {
      return "PC";
    }
  };

  //Fetching list of users
  useEffect(() => {
    fetch(
      "https://raw.githubusercontent.com/iamVictorSam/react-mentions-with-form/7d03dd94f7ae1740e835bef959d704ca81d1355b/src/names.json"
    )
      .then((response) => response.json())
      .then((json) => {
        const mentionableNames = json.people.map((person) => ({
          id: person.name,
          display: person.name,
        }));
        setDataResp(mentionableNames);
      })
      .catch((error) => console.log(error));
  }, []);
    
    return ();
};

export default CommentForm;

```

From the code block above, we’ve created some React states that we will be using to hold data from our form inputs. We’ve also handled our form submission by generating random numbers, getting the current date and time, getting the platform type, and adding all this data to the `newComment` state. We’re also fetching a List of users when the app initializes from an external URL. 

Finally, update the return statement with the code below.

```jsx
return (
  <div>
    {/* Displaying User's comment */}
    {submittedComment && (
      <div className={styles.commentTile}>
        <div>
          <strong>User #{submittedComment.id}</strong> - {submittedComment.name}
        </div>
        <div>Email: {submittedComment.email}</div>
        <div>
          Comment: <strong> {submittedComment.comment}</strong>
        </div>
        <div>ID: {submittedComment.id}</div>
        <div>Date: {submittedComment.date}</div>
        <div>Platform: {submittedComment.platform}</div>
      </div>
    )}

    <form className={styles.container} onSubmit={handleSubmit}>
      <div className={styles.form_group}>
        <label className={styles.label} htmlFor="name">
          Name:
        </label>
        <input
          className={styles.input}
          type="text"
          id="name"
          value={name}
          onChange={(event) => setName(event.target.value)}
        />
      </div>

      <div className={styles.form_group}>
        <label className={styles.label} htmlFor="email">
          Email:
        </label>
        <input
          className={styles.input}
          type="email"
          id="email"
          value={email}
          onChange={(event) => setEmail(event.target.value)}
        />
      </div>

      <div className={styles.form_group}>
        <label className={styles.label} htmlFor="comment">
          Comment:
        </label>
        {/* Using the Mention Component */}
        <MentionsInput
          value={comment}
          classNames={mentionStyle}
          onChange={(event, newValue) => setComment(newValue)}
        >
          <Mention
            trigger="@"
            data={dataResp}
            className={mentionStyle.mentions__mention}
          />
          <Mention
            trigger="#"
            data={dataResp}
            className={mentionStyle.mentions__mention}
          />
        </MentionsInput>
      </div>

      <button className={styles["submit-btn"]} type="submit">
        Submit
      </button>
    </form>
  </div>
);
```

In the code above, we have assigned the respective states to our inputs. We’ve also added a React-Mentions components with two trigger patterns  (@ and #). Upon submission of the form, the `handleSubmit` function created earlier is called, and our response is displayed at the top of the form.

With all this done, we'll have results like the one below.

![-](https://blog.openreplay.com/images/building-a-comment-form-with-react-mentions/images/s_3AB75596E32609F9CCC4A2A1E17BAABFCECBC8D11BB2CA0CEF7A0C9709F968A2_1686055261899_ezgif.com-video-to-gif+1.gif)


## Conclusion
React-Mentions provides a powerful and intuitive solution for implementing the mention functionality in React applications. By integrating this library, developers can effortlessly enable users to mention other participants and bring them into the conversation. With its customizable triggers, suggestions, and styling options, React-Mentions offers a seamless user experience. Whether for social media platforms, collaborative tools, or communication applications, React-Mentions empowers developers to enhance interactivity and engagement in their applications. 

Here is the Link to the [source code](https://github.com/iamVictorSam/react-mentions-with-form) on GitHub.