Skip to content
Tier

useArrivals

Pro

Calls onNew with the ids that weren't there before: the way to raise a sound or a signal from data, never from a mount. The ids present at the first render are the ones that were already waiting when the page drew, so they are not news and onNew is never called for them. After that, each render that brings an id the hook hasn't seen calls onNew once with all the new ids together (a burst is one call), and an id that goes away and comes back is new again. Feed it what the service reports, such as the adapters' waiting approvals or finished runs; don't feed it what a component renders.

const attention = useAttention({ sound: { enabled, when: "away" } })
useArrivals(waiting.map((a) => a.id), () => attention.signal({ kind: "approval", title: "An approval is waiting" }))
Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0 and 2.3.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/use-arrivals

Brings in: tokens

Usage

TSX · The example above
"use client"

import * as React from "react"
import { useArrivals } from "@/lib/candor/use-arrivals"
import { Button } from "@/components/candor/ui/button"

/*
 * Two approvals were already waiting when this example drew, so they are not news and nothing is announced for them.
 * Press the button and a third arrives from "the service": that id wasn't there before, so the callback runs once.
 * Feed the hook what a service reports, never what a component renders, so a page load or a re-render stays quiet.
 */
export default function Example() {
  const [waiting, setWaiting] = React.useState(["approve-batch-size", "approve-export"])
  const [heard, setHeard] = React.useState<string[]>([])
  useArrivals(waiting, (ids) => setHeard((h) => [...h, ...ids]))
  return (
    <div className="flex flex-col items-start gap-3 text-sm">
      <p>
        Waiting on you: <strong>{waiting.length}</strong>. Announced as new: <strong>{heard.length}</strong>
        {heard.length > 0 && <> ({heard.join(", ")})</>}.
      </p>
      <Button size="sm" variant="outline" onClick={() => setWaiting((w) => [...w, `approve-${w.length + 1}`])}>
        A new approval arrives
      </Button>
    </div>
  )
}

Functions

useArrivals(ids: readonly string[], onNew: (ids: string[]) => void)