useView

Open in

Subscribe to a View and return the visible node list with pagination, branch navigation, and write operations. The hook re-renders the component on every view update.

This hook must be used within a TransportProvider or a ChatTransportProvider.

React

1

2

3

4

5

6

7

8

9

10

11

12

import { useView } from '@ably/ai-transport/react';

function Chat() {
  const { messages, send, loadOlder, hasOlder } = useView({ limit: 30 });

  return (
    <div>
      {hasOlder && <button onClick={() => loadOlder()}>Load older</button>}
      {messages.map((m) => <Message key={m.id} message={m} />)}
    </div>
  );
}

Parameters

transportoptionalClientTransport<TEvent, TMessage> or Null
Client transport whose default view to subscribe to. Defaults to the nearest provider when omitted.
viewoptionalView<TEvent, TMessage> or Null
A specific View to subscribe to directly. Takes priority over transport.
limitoptionalNumber
Maximum number of older messages to load per page. When provided, auto-loads the first page on mount (SWR-style).
skipoptionalBoolean
When true, skip all subscriptions and return an empty handle.

Returns

ViewHandle<TEvent, TMessage>

messagesTMessage[]
The visible domain messages along the selected branch.
nodesMessageNode<TMessage>[]
Visible conversation nodes along the selected branch.
hasOlderBoolean
Whether older messages can be revealed via loadOlder.
loadingBoolean
Whether a page load is currently in progress.
loadErrorAbly.ErrorInfo or Undefined
Set when the most recent loadOlder failed; cleared on the next successful load.
loadOlderFunction
selectFunction
getSelectedIndexFunction
getSiblingsFunction
hasSiblingsFunction
getNodeFunction
sendFunction
regenerateFunction
editFunction
updateFunction

Load older messages

loadOlder: () => Promise<void>

Load older messages into the view. No-op if already loading. On failure, loadError is set; on success, loadError is cleared.

Select a sibling

select: (msgId: string, index: number) => void

Select a sibling at a fork point by index. Updates this view's branch selection and triggers a re-render with the new branch visible.

Get the selected sibling index

getSelectedIndex: (msgId: string) => number

The index of the currently selected sibling at a fork point.

Get sibling messages

getSiblings: (msgId: string) => TMessage[]

Every sibling message at a fork point, ordered chronologically by serial.

Check for siblings

hasSiblings: (msgId: string) => boolean

Whether a message has sibling alternatives. Use this to decide whether to render branch-navigation arrows.

Get a node by ID

getNode: (msgId: string) => MessageNode<TMessage> | undefined

The node for a given message ID, or undefined if the tree has no such node.

Send messages

send: (messages: TMessage | TMessage[], options?: SendOptions) => Promise<ActiveTurn<TEvent>>

Send one or more user messages and start a new turn. The parent is auto-computed from this view's selected branch unless overridden in options.

Regenerate a response

regenerate: (messageId: string, options?: SendOptions) => Promise<ActiveTurn<TEvent>>

Regenerate an assistant message. Creates a new turn that forks the target message with no new user messages.

Edit a user message

edit: (messageId: string, newMessages: TMessage | TMessage[], options?: SendOptions) => Promise<ActiveTurn<TEvent>>

Edit a user message and start a new turn from that point. The original message and its descendants remain in the tree as a separate branch.

Update an existing message

update: (msgId: string, events: TEvent[], options?: SendOptions) => Promise<ActiveTurn<TEvent>>

Update an existing message in place and start a continuation turn. Commonly used for delivering client-executed tool results.

See View for the full method semantics and the ActiveTurn shape returned by the write operations. Each returned promise rejects with an ErrorInfo on failure.

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

import { useView } from '@ably/ai-transport/react';
import { useState } from 'react';

function Chat() {
  const { messages, hasOlder, loadOlder, send, regenerate } = useView({ limit: 30 });
  const [input, setInput] = useState('');

  const onSubmit = async (e) => {
    e.preventDefault();
    if (!input.trim()) return;
    const text = input;
    setInput('');
    await send({ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text }] });
  };

  return (
    <div>
      {hasOlder && <button onClick={() => loadOlder()}>Load older</button>}
      {messages.map((m) => (
        <div key={m.id}>
          <strong>{m.role}:</strong> <Parts parts={m.parts} />
          {m.role === 'assistant' && <button onClick={() => regenerate(m.id)}>Regenerate</button>}
        </div>
      ))}
      <form onSubmit={onSubmit}>
        <input value={input} onChange={(e) => setInput(e.target.value)} />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}