Portal Community

Signature

function useInteractionCallback<TData = unknown>(
  interactionId: string | null
): {
  /** The response, once received */
  response: InteractionResponse<TData> | null;

  /** True if timed out or an error occurred */
  error: InteractionError | null;

  /** True while waiting for a response */
  isPending: boolean;

  /** True if the response has been received */
  isResolved: boolean;
}

Usage — React-Initiated Approval

This pattern is for cases where a React component initiates an interaction via an API call (not via useInteraction()) and wants to observe the response:

import { useInteractionCallback } from 'edge-interact-react';

function WorkflowApprovalStatus({ workflowId }: { workflowId: string }) {
  const [interactionId, setInteractionId] = useState<string | null>(null);
  const { response, error, isPending } = useInteractionCallback(interactionId);

  useEffect(() => {
    // Fetch the interaction ID for this workflow from the server
    workflowApi.getHilInteractionId(workflowId).then(setInteractionId);
  }, [workflowId]);

  useEffect(() => {
    if (response) {
      // Update UI when the manager responds
      console.log('Manager decision:', response.outcome, response.respondedBy);
    }
  }, [response]);

  if (!interactionId) return <p>Loading...</p>;

  return (
    <div className="approval-status">
      {isPending && (
        <div className="pending-badge">
          Waiting for manager approval...
        </div>
      )}
      {response && (
        <div className={`decision-badge ${response.outcome}`}>
          {response.outcome === 'approved' ? 'Approved' : 'Rejected'} by {response.respondedBy}
        </div>
      )}
      {error && (
        <div className="error-badge">
          {error instanceof InteractionTimeoutError
            ? 'Approval timed out — no response received.'
            : `Error: ${error.message}`}
        </div>
      )}
    </div>
  );
}

Null interactionId

Pass null as interactionId when there is no active interaction to watch. The hook returns { response: null, error: null, isPending: false, isResolved: false } and does not create any subscriptions.

Cleanup

The hook cleans up automatically when: