Back

How to integrate React with Slack

How to integrate React with Slack

Feedback channels can be comment sections, feedback widgets, or email forms on a website. In this article, you will learn how to create a feedback widget that posts messages to a dedicated Slack channel - and you’ll create that component using React.

Feedback provides a channel of communication between clients and organizations. Clients use feedback channels to communicate their satisfaction or dissatisfaction with a product or service. Feedback provides valuable insight into clients’ needs and enables organizations to make decisions that give customer satisfaction a priority.

Feedback is important in software development and technical documentation. Developers use feedback channels to direct attention to the part of technical documentation that is unclear or a feature that is missing or poorly implemented in a web application or software. Let’s see how to use React to build a feedback component.

Set up a Slack App

In this section, readers will learn how to create a Slack app and install the app on an existing Slack channel. The section consists of two sub-sections. The first sub-section gives a step-by-step description of how to create a feedback channel. The second sub-section explains how to create a Slack app and how to link the app with the feedback channel.

Creates a channel to receive feedback

Open the Slack desktop app or point your browser to https://slack.com/signin to access your Slack account. In your current workspace, go to the left panel as shown below.

slackworkspace Click the “Add Channel” menu to create a channel. In the pop-up menu, select “Create new channel”.

slackchanne2

Name the channel “feedback” as shown above. Click the “Next” button, and choose “Public”, as shown below.

slackchannel3

Click the “Create” button shown above. The newly created feedback channel will appear in the list of channels in the current workspace.

Create a Slack App and install it to the feedback channel

Open the https://api.slack.com/apps/new website in your web browser. Click on “Create New App”. Choose “From scratch” from the pop-up menu that appears, as seen in the image below.

slackcreateApp

Fill in the name of your app as shown below. Select the workspace to develop your app.

slackcreateapp2

Click the “Create App” button. On the new page, scroll down and select “Install to Workspace”. Input the name of the channel you created earlier in the text box, as shown below.

slackworkspace 2

Click “Allow”. Next, click on “Add Features and Functionality”, and select “Incoming Webhooks”. Scroll down, then copy the webhook URL to a safe place. Next, we will create a React component that will use the webhook URL to post messages to the feedback slack channel.

React feedback component

This section explains how to create a Feedback component using React. The reader will learn how to scaffold a React project using Vite and install dependencies. It also describes how to create a feedback component that permits users to input text.

Create a react app and install dependencies

We will use Vite to scaffold the React project. Open your favorite CLI, run the command below, and follow the prompts.

npm create vite@latest feedback-app -- --template react

The above code creates a React project with the name feedback-app. Run the code below to install dependencies for the project.

cd feedback-app 
npm install
npm install react-icons

You should see a folder structure like the one below.

appstructure

Launch your favorite code editor to edit the files in the feedback-app folder. For this article, we will use VS Code. Open the feedback-app folder in VS Code.

To test the installation. Run the code below.

npm run dev

A “Vite + React” page should be available at http://localhost:5173/. In the VS Code, open the App.jsx file. Delete all the content within the div tag. The page in the browser becomes blank. Also, open the App.css and index.css files and delete their contents. Open the index.html file, and change the title to Feedback.

Creates a feedback component

In the src folder, create two sub-folders:

  • components
  • scripts

In the components sub-folder, create two files:

  • Form.jsx
  • Feedback.jsx

Open the Form.jsx file, and write the code below.

import React, { useState } from 'react';
import { FaEnvelope, FaComment, FaSmile } from 'react-icons/fa'

The code above imports the required packages. Create a component and name it Form as shown below.

const Form = () => {
  return <div>Form</div>;
};
export default Form;

Within the return statement, create a form element. The form element will contain a text input, textarea, and a button element as children. Give each element a class name for CSS styling, as shown below.

const Form = () => {
  return (
    <form className="feedback-form">
      <div className="formelement-container">
        <label className="formlabel">
          <FaSmile style={{ marginRight: 3 }} />
          Is this page useful?
        </label>
      </div>
      <div className=" formelement-container">
        <label htmlFor="email" className="formlabel ">
          <FaEnvelope style={{ marginRight: 3, padding: 3 }} />
          Email Address
        </label>
        <input
          type="email"
          name="email"
          className="form-input element-border"
          required
        />
      </div>
      <div className="formelement-container">
        <label htmlFor="msg" className="formlabel">
          <FaComment style={{ marginRight: 3 }} />
          Your Feedback:
        </label>
        <textarea
          className="element-border"
          id="msg"
          name="msg"
          rows="4"
          cols="20"
          required
        ></textarea>
      </div>
      <button className="form-button element-border" type="submit">
        Submit{" "}
      </button>
    </form>
  );
};
export default Form;

Create two state variables in the Form component as shown below to store the value from the input element and textarea.

const [comments, setComment] = useState(" ");
const [email, setEmail] = useState(" ");

To handle inputs, implement two functions in the Form component, handleEmail and handleTextArea. The function handleEmail will set the value of the email and handleTextArea will set the value of the comments. To handle form submission, implement a submitForm function. The function will pass the email and comments to the props from the parent component. See the implementation below.

import React, { useState } from "react";
import { FaEnvelope, FaComment, FaSmile } from "react-icons/fa";

const Form = ({ handleSubmit }) => {
  const [comments, setComment] = useState(" ");
  const [email, setEmail] = useState(" ");

  const handleTextArea = (e) => {
    setComment(e.target.value);
  };
  const handleEmail = (e) => {
    setEmail(e.target.value);
  };
  const submitForm = (e) => {
    e.preventDefault();
    const data = { email: email, comments: comments };
    handleSubmit(data);
    setEmail(" ");
    setComment(" ");
  };

  return (
    <form onSubmit={submitForm} className="feedback-form">
      <div className="formelement-container">
        <label className="formlabel">
          <FaSmile style={{ marginRight: 3 }} />
          Is this page useful?
        </label>
      </div>
      <div className=" formelement-container">
        <label htmlFor="email" className="formlabel ">
          <FaEnvelope style={{ marginRight: 3, padding: 3 }} />
          Email Address
        </label>
        <input
          type="email"
          name="email"
          className="form-input element-border"
          value={email}
          required
          onChange={handleEmail}
        />
      </div>
      <div className="formelement-container">
        <label htmlFor="msg" className="formlabel">
          <FaComment style={{ marginRight: 3 }} />
          Your Feedback:
        </label>
        <textarea
          className="element-border"
          value={comments}
          id="msg"
          name="msg"
          rows="4"
          cols="20"
          required
          onChange={handleTextArea}
        ></textarea>
      </div>
      <button className="form-button element-border" type="submit">
        Submit{" "}
      </button>
    </form>
  );
};
export default Form;

To style the Form component, open the App.css and style accordingly as shown below.

.feedback-form {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 4px;
  row-gap: 10px;
}

.formelement-container {
  display: flex;
  flex-direction: column;
  text-align: left;
}

.formlabel {
  display: flex;
  flex-direction: row;
  padding: 2px;
  font-size: 17px;
}

.form-input {
  height: 40px;
  padding: 2px;
}

.element-border {
  border: 2px solid #d5d0d0;
  border-radius: 4px;
}

.form-button {
  background-color: #ff0000;
  height: 40px;
  width: 100%;
}

Next, create a file in the components sub-folder. Name the file Feedback.jsx. In the file, import the needed packages and theForm component as shown below.

import React, { useState } from 'react';
import { FaWindowClose } from 'react-icons/fa';
import Form from './Form';

Create a component and name it Feedback as shown below.

const Feedback = () => {
  return <div>Feedback</div>;
};

Create a state variable and set the initial value to false as shown in the code below.

const [showForm, setShowForm] = useState(false);

Within the return statement of the Feedback component, create a button element and div element. The div element will contain the Form component created earlier. When you click the button element, a form pops up.

To display and close the Form component, we will implement two functions in the Feedback component, openPopUp and closePopUp. The openPopUp will set the state variable showForm to true while closePopUp will set the variable to false. We will then attach a click event listener to the button to trigger the openPopUp.

To close the popup, we will attach a click event listener to a close icon. Next, create a handleSubmit function in the Feedback component. Pass this function as props to the Form component to process form data. See the code implementation below.

import React, { useState } from "react";
import { FaWindowClose } from "react-icons/fa";
import Form from "./Form";

const Feedback = () => {
  const [showForm, setShowForm] = useState(false);

  const openPopUp = () => {
    setShowForm(true);
  };

  const closePopUp = () => {
    setShowForm(false);
  };
  const handleSubmit = (data) => {};

  return (
    <div>
      <button className="feedback-button element-border" onClick={openPopUp}>
        Feedback
      </button>
      {showForm && (
        <div className="feedback-modal ">
          <FaWindowClose
            onClick={closePopUp}
            className="feedback-closewindow "
          />

          <Form handleSubmit={handleSubmit} />
        </div>
      )}
    </div>
  );
};
export default Feedback;

Add the styles below to the App.css file.

.feedback-button {
  position: fixed;
  top: 50%;
  bottom: 50%;
  left: 45%;
  background-color: #ff0000;
  height: 40px;
  width: 100px;
  color: #ffffff;
  padding: 2px;
}
.feedback-modal {
  display: flex;
  flex-direction: column;
  z-index: 3000;
  width: 50%;
  position: fixed;
  top: 30%;
  left: 30%;
  background-color: rgb(254, 255, 255);
  box-shadow:
    0 4px 8px 0 rgba(0, 0, 0, 0.2),
    0 6px 20px 0 rgba(0, 0, 0, 0.19);
  padding: 10px;
  border-radius: 4px;
  row-gap: 2px;
}
.feedback-closewindow {
  align-self: flex-end;
  margin: 2px;
}
@media screen and (min-width: 999px) {
  .feedback-modal {
    width: 30%;
  }
}

The CSS code above styles the elements in the Feedback component.

To view what has been done so far, open the App.jsx file, import the Feedback component, and render within the return statement of the App component as shown below.

import React, { useState } from "react";
import Feedback from "./components/Feedback";
import "./App.css";

function App() {
  return (
    <>
      <div>
        <Feedback />
      </div>
    </>
  );
}

export default App;

A button centered at the center of the page should be visible, the button when clicked should display a feedback form like the one below. slackform1

Send messages from the feedback component to a Slack channel

This section describes how to use the Slack API to post a message from the feedback component to the Slack channel.

Create a file in the scripts folder and name it slack.js. Open the slack.js file and create an async function as shown below.

const slackCall = async (url, data) => {
  const response = await fetch(`${url}`, {
    method: "POST",
    body: JSON.stringify({ text: `${data.comments}  by ${data.email}` }),
  });
  return response;
};

The slackCall function in the code above takes two parameters, url and a data object. The function makes a POST call to the URL endpoint with the data parameter as the body. The request body must have a text field for the message to appear in the Slack channel.

In the root of the feedback-app folder, create a .env file. Open the .env file and write VITE_HOOK_URL= "WEBHOOK_URL" replace the WEBHOOK_URL with the webhook URL of the Slack app.

import slackCall from "../scripts/slack";

Create a variable as shown below.

const api_url = import.meta.env.VITE_HOOK_URL;

Vite permits the import of environmental variables with import.meta.env.

In the submitForm function, pass the api_url and data returned from the Form component as parameters to the slackCall function. To handle the response from the Slack API call, create two state variables as shown in the code below.

const [success, setSuccess] = useState(false);
const [error, setError] = useState(false);

Next, update the Feedback component as shown below.

import React, { useState } from "react";
import { FaWindowClose } from "react-icons/fa";
import Form from "./Form";
import slackCall from "../scripts/slack";

const api_url = import.meta.env.VITE_HOOK_URL;

const Feedback = () => {
  const [showForm, setShowForm] = useState(false);
  const [success, setSuccess] = useState(false);
  const [error, setError] = useState(false);

  const openPopUp = () => {
    setShowForm(true);
  };

  const closePopUp = () => {
    setShowForm(false);
  };
  const handleSubmit = async (data) => {
    const response = await slackCall(api_url, data);
    if (response.status == 200) {
      setSuccess(true);
    } else {
      setError(true);
    }
  };
  return (
    <div>
      <button className="feedback-button element-border" onClick={openPopUp}>
        Feedback
      </button>
      {showForm && (
        <div className="feedback-modal ">
          <FaWindowClose
            onClick={closePopUp}
            className="feedback-closewindow "
          />
          {success && <p>Your feedback has been submitted successfully</p>}
          {error && <p>An error occurred</p>}

          <Form handleSubmit={handleSubmit} />
        </div>
      )}
    </div>
  );
};
export default Feedback;

Go to the browser and post a message with the feedback form. A message should appear in the Slack channel.

Conclusion

Feedback is a channel of communication between clients and organizations. Feedback directs organizations’ attention to specific clients’ problems that need attention. This article has demonstrated how to create a feedback component that posts messages into a Slack channel. The article demonstrated how to create a Slack app and how to use the Slack API.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay