useTyping

Open in

The useTyping hook manages typing indicator state for a chat room, automatically tracking users who are currently typing and updating state in realtime.

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import { useTyping } from '@ably/chat/react';

const MyComponent = () => {
  const { keystroke, stop, currentTypers } = useTyping();

  return (
    <div>
      {currentTypers.length > 0 && (
        <p>{currentTypers.map(t => t.clientId).join(', ')} typing...</p>
      )}
      <input
        onInput={() => keystroke()}
        onBlur={() => stop()}
      />
    </div>
  );
};

This hook must be used within a ChatRoomProvider.

Parameters

The useTyping hook accepts an optional configuration object:

listeneroptionalTypingListener
A callback invoked whenever a typing event occurs. Removed when the component unmounts.
onDiscontinuityoptionalDiscontinuityListener
A callback to detect and respond to discontinuities.
onRoomStatusChangeoptionalRoomStatusChange
A callback invoked when the room status changes. Removed when the component unmounts.
onConnectionStatusChangeoptionalConnectionStatusChange
A callback invoked when the connection status changes. Removed when the component unmounts.

Returns

The useTyping hook returns an object with the following properties:

currentTypersTypingMember[]
The set of users currently typing in the room, with associated metadata. Updated automatically from room events.
keystrokekeystroke()
Sends a typing-started notification.
stopstop()
Sends a typing-stopped notification.
roomStatusRoomStatus
The current status of the room, kept up to date by the hook.
roomErrorErrorInfo or Undefined
An error object if the room is in an errored state.
connectionStatusConnectionStatus
The current connection status, kept up to date by the hook.
connectionErrorErrorInfo or Undefined
An error object if there is a connection error.

Start typing

keystroke(): Promise<void>

Sends a typing started event to notify other users that the current user is typing.

Events are throttled according to the heartbeatThrottleMs room option to prevent excessive network traffic. If called within the throttle interval, the operation becomes a no-op.

Returns

Promise<void>

Returns a promise. The promise is fulfilled when the typing event has been sent, or rejected with an ErrorInfo object.

Stop typing

stop(): Promise<void>

Sends a typing stopped event to notify other users that the current user has stopped typing.

If the user is not currently typing, this operation is a no-op.

Returns

Promise<void>

Returns a promise. The promise is fulfilled when the typing stopped event has been sent, or rejected with an ErrorInfo object.

Example

React

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

import { useTyping } from '@ably/chat/react';
import { useState, useCallback } from 'react';

function MessageInput({ onSend }) {
  const [text, setText] = useState('');
  const { keystroke, stop, currentTypers } = useTyping({
    listener: (event) => {
      const { change } = event;
      if (change.type === 'typing.started') {
        console.log(`${change.clientId} started typing`);
      }
    },
  });

  const handleInput = useCallback((e) => {
    setText(e.target.value);
    if (e.target.value.length > 0) {
      keystroke();
    } else {
      stop();
    }
  }, [keystroke, stop]);

  const handleSubmit = useCallback(async () => {
    await onSend(text);
    setText('');
    await stop();
  }, [text, onSend, stop]);

  return (
    <div>
      {currentTypers.length > 0 && (
        <p>
          {currentTypers.length === 1
            ? `${currentTypers[0].clientId} is typing...`
            : `${currentTypers.map(t => t.clientId).join(', ')} are typing...`}
        </p>
      )}
      <input value={text} onChange={handleInput} onBlur={() => stop()} />
      <button onClick={handleSubmit}>Send</button>
    </div>
  );
}