Demo React bindings over the same vanilla core Full check-in demo →

Same core, React bindings

The library is a plain async function with no framework dependency. A binding owns three things: the responder list the page renders (resolved from a policy), the one call, and its state. This page's useCheckin hook is all of it; the Angular example is the same as a service.

The whole binding

export function useCheckin(request, policy) {
  const [responders, setResponders] = useState([]);
  const [state, setState] = useState({ status: "idle" });

  // who may answer in this browser — availability and the default come back in the list
  useEffect(() => { void resolveResponders(policy).then(setResponders); }, [policy]);

  const start = useCallback(async (responder = responders.find((r) => r.isDefault)) => {
    setState({ status: "waiting" });
    try {
      const response = await requestCheckin(request, {
        getCredential: credentialGetterFor(responder, { origin: policy.origin }),
      });
      setState({ status: "done", response });
    } catch (e) {
      setState(e instanceof CheckinFlowError && e.outcome.status === "declined"
        ? { status: "declined" }
        : { status: "error", error: String(e) });
    }
  }, [request, policy, responders]);

  return { ...state, responders, start };
}

// …and the component renders the list: one button per responder, the default leading
{responders.map((r) => ( className={r.isDefault ? "smart-btn primary" : "smart-btn"}
          disabled={!r.available} title={r.reason} onClick={() => start(r)}>
    {r.name}
  </button>
))}