Building a Slack integration in React

How to let users authorize and select Slack channels in your app with Knock's SlackKit.

Our @knocklabs/react library comes with pre-built components for allowing your users to connect their Slack workspace to Knock and select the channels they want to be notified on. lackKit manages your OAuth connection and tokens, helps your customers select which channels they want to receive notifications in, and integrates seamlessly with the rest of Knock.

You can follow the guide on SlackKit here.

Getting started

To get started you'll need a Knock account, a Slack channel connected to a Slack app, and a workflow with a Slack channel step.

You'll also need the following data to use in your SlackKit components:

Required credentials

Here's where to find each setup data variable and a recommendation of how to make it available to your client application.

Slack app client ID

The client ID of your Slack application.

  • Find it in your Slack app's Basic info section, or saved in the Knock Slack channel you set up in the first step of the process.
  • Store it as an .env variable.

Knock Slack Channel ID

This is the ID of the Slack channel in the Knock dashboard that you linked your Slack application to.

  • Find it in the Knock dashboard in the channel itself.
  • Store it as an .env variable.

User JWT token with resource access grants

This is a token you will generate that contains info about the user and what resources they have access to in your Knock account.

  • Find it: Token generated for the user from your application.
  • Store it in local storage for your user.

Knock entities

SlackKit uses parts of Knock's data model to facilitate OAuth and channel selection using the React components outlined below.

🚨
Note: If this is the first time you've thought about objects and tenants in Knock, we'd recommend reviewing how they work with SlackKit on the integration overview page before proceeding.

Tenant ID

This is the ID of the tenant that will be storing the Slack access token. You will want one tenant per Slack workspace, which is generally one per customer you support. You will use this tenant to trigger notifications for the Slack workflow so your channels all have the same access token.

💡
Note: You do NOT need to create your tenant with the Knock API before using it in our SlackKit components. The tenant will be created automatically with the ID you provide when the user connects their Slack workspace.
  • Find it: In most cases, you should use the UUID that represents your user's organization in your system. For example, if your user is part of the Jurassic Park organization, you could create a tenant ID of jurassic-park.
  • Store it: This tenant ID should either be stored in or generated from data about the organization you support here.

Recipient object ID and collection

This is the ID and collection of the object that will be used as the recipient for your Slack notification workflow. The object will store the Slack channels your user selects to notify. When you use this object as the recipient of your workflow, it will send a notification to any Slack channels stored on it. Slack channels are stored on the object as ChannelData.

💡
Note: You do NOT need to create your object with the Knock API before using it in our SlackKit components. The object will be created automatically when the user connects their Slack channel to the object.
  • Find it: You can generate an object ID and collection to serve as the recipient object. We suggest basing this on the item you're sending a notification about. For example, if you have a collection of videos and a user wants to be notified about the comments on the dinosaurs-loose video, your object collection could be videos and the ID dinosaurs-loose.
  • Store it: This object ID and collection should either be stored in or generated from data about the item you're sending notifications about.

Using SlackKit components

Once you've provided access to the necessary data, you can drop Knock's pre-built components into your React application to immediately set up Slack authorization and channel selection for your users. See the reference for full documentation of these components.

Add the providers

In order to give your components the data they need, they must be wrapped in the KnockSlackProvider. We recommend putting this high in your component tree so that any Slack components that you use will be rendered within it. The Slack provider goes inside of the KnockProvider. Your hierarchy will look like this:

The KnockSlackProvider gives your components access to the status of the connection to your Slack app, so that they can all be in sync when a user is connecting, disconnecting, or experiencing a connection error.

Add the components

SlackAuthButton & Container

Your users will give your Slack app access to their own Slack workspaces via the SlackAuthButton. This button can be used on its own, or nested in the SlackAuthContainer for a bigger visual footprint. Here's an example of how to use them:

The SlackAuthButton maps a tenant in your product to a customer's Slack workspace. This means in most cases you'll just need a single instance of the SlackAuthButton.

Remember to consider which roles in your application can access the SlackAuthButton component. Knock does not control access to the component. In most cases, you'll add this connect button/container in the settings area of your product.

SlackChannelCombobox

This combobox contains the list of channels in the connected Slack workspace. Users will use this combobox to search and select a channel (or more than one channel) to be notified when an event in your application occurs, for example a comment on a video. They can also use this combobox to deselect a connected channel.

The combobox has an option to show connected channels below it, which is a list of channel tags. This is useful to show the user which channels are already connected, and gives them an easy way to remove them as well.

Add your combobox to your application where you'd like the user to select channels to notify:


💡
Limitations
  • The combobox will only show channels for Slack workspaces with fewer than 1000 channels (public and private; not including archived). If there are more, the combobox will turn into a text input that accepts a channel ID to connect.
  • The combobox will only show private channels from your users' Slack workspaces if your Slack app has been invited to those channels.
  • The combobox does not show individual users for Slack direct messages.

Complete sample code

Here's an example of these components in a React application.





Using SlackKit headless

If you need custom designs or want to display additional information around your Slack integration, you don't need to use Knock's pre-built components to take advantage of SlackKit.

SlackKit exposes three levels of support: React hooks, client functions, and API endpoints.

Hooks

You can use the Slack React hooks under the hood to access and set Slack integration data with your own components. All of them are available from the @knocklabs/react-core package. All of them must still be nested under the KnockSlackProvider to work.

To use a hook in your component, all you need to to is import it and pass it the necessary params, and then you can use the data and functions returned in each to pass to your own component UI.

For example, you may want to provide your users a list of the connected channels outside of the SlackChannelCombobox. Let's look at how you can combine two hooks to accomplish that.

Building a list of connected channels

First, make sure your component that you're using the hooks in is nested somewhere under the KnockSlackProvider. Then, import both the useSlackChannels and useConnectedSlackChannels hooks, as we'll be combining data from each to build our list.

We'll combine our data to create a list of channels that has a name and an isPrivate attribute so we can conditionally show a lock icon if the channel is marked private.

Here's some sample code for our final list:

Client functions

If you want more fine grain control of your data, you can skip the hooks and simply use the functions Knock exposes in the @knocklabs/client library as long as you wrap the component you're calling it in inside of KnockProvider. You can accomplish anything we provide with hooks or the components with the following functions:

  • knock.slack.authCheck: Get the status of Slack authorization
  • knock.slack.getChannels: Get a list of Slack channels for the given tenant
  • knock.slack.revokeAccessToken: Disables an access token with Slack and removes it from the tenant
  • knock.objects.getChannelData: Use this to get the connected channels stored as channel data on the recipient object
  • knock.objects.setChannelData: Use this to set the connected channels for a recipient object or an access token for a tenant

API endpoints

Lastly, you can interact directly with the API endpoints for all of the above functionality. Here are the endpoints used in SlackKit that you would need to support an implementation of the managed UI:

  • Slack auth check: status of Slack authorization
  • Slack channels: list of Slack channels for the given workspace
  • Slack revoke token: revoke Slack app token access and remove from tenant
  • Get channel data: get channel data for your recipient object, which gives you access to the connected slack channels
  • Set channel data: set channel data for your recipient object, which allows you to set connected slack channels