Yes! You can do all the things that you'd expect in a classical component in a functional component.

Below is an example of a functional component built with Ably and React, you can also see it in this gist:

import React, { useState, useEffect } from 'react';
import Ably from "ably/promises";

const client = new Ably.Realtime("your-api-key-here");

const Component = (props) => {

  const channel = client.channels.get('some-channel');
  const [ messages, updateMessages ] = useState([]);

  useEffect(() => {
    async function subscribe() {      
      await channel.subscribe(message => {
        console.log("A message was received", message);

        const newMessages = messages.slice();



    return function cleanup() {
  const sendMessage = () => {
    channel.publish({ name: "myEventName", data: { text: "Your message goes here." } });

  return (
      <button onClick={ (e) => sendMessage(e) }>Click here to send a message</button>
      <h2>Messages will go here:</h2>
        {, index) => (<li key={"item" + index}>{text}</li>)) }

export default Component;

In this example:

  • Create a functional component called Component
  • Create an instance of the Ably client, and a channel inside the component function.
  • Define a variable with useState called messages, along with it's corresponding updateMessages function.
  • Then use useEffect to manage your subscriptions.
  • Three important things are happening in here:
    1. Subscribing to a channel, along with a callback that updates our messages by calling updateMessages.
    2. The subscription function is wrapped and called async to prevent race conditions in React. Call it using subscribe() inside of the useEffect callback.
    3. Return a cleanup function, that unsubscribes from the channel.

This example uses a sendMessage function with syntax of the form 

const sendMessage = () => { ... }

rather than function sendMessage(){} so that it can be defined in the body of the functional component.

It is important to ensure that your cleanup function contains an unsubscribe call, so you don't accidentally create lots of Ably connections while developing/testing.

Please note - the above example uses the Ably API key in the constructor call to Ably.Realtime. In a production scenario, you should use Token Authentication instead, as putting your Ably API key directly into your React JSX markup exposes your API key to theft and abuse.