Guías
Ver como MarkdownReact
Provider, hooks y el botón hospedado en una aplicación de React.
npm install @andco/sdk @andco/sdk-reactMontar el provider
import { AndcoProvider } from "@andco/sdk-react";
const clientOptions = {
clientId: import.meta.env.VITE_ANDCO_CLIENT_ID,
redirectTo: new URL("/", window.location.origin).href,
initialScopes: ["openid", "email", "profile"],
} as const;
export function App() {
return (
<AndcoProvider clientOptions={clientOptions}>
<Account />
</AndcoProvider>
);
}El provider construye la instancia con un inicializador perezoso. Es seguro en StrictMode y bajo Suspense: construir no hace entrada ni salida, y el almacén de sesión solo empieza a cargar cuando algo se suscribe, cosa que React hace al confirmar el render, no al ejecutarlo.
Leer la sesión
import { useAndcoSession } from "@andco/sdk-react";
export function Account() {
const session = useAndcoSession();
if (session === undefined) return <Skeleton />;
if (!session) return <SignIn />;
return <p>{session.user.email}</p>;
}Los tres estados importan. Tratar undefined como «sin sesión» hace parpadear la pantalla de ingreso en cada carga.
useAndcoUser() devuelve directamente la persona, con los mismos tres estados.
El botón
import { AndcoButton } from "@andco/sdk-react";
<AndcoButton
authorization={{ scopes: ["openid", "email", "profile"] }}
onComplete={() => console.log("done")}
onError={(error) => setMessage(error.message)}
/>;El botón es una superficie de Andco dentro de un iframe que React monta y desmonta. No acepta endpoints, clientId ni tema: eso lo toma de la instancia, para que no existan dos copias de un mismo valor que puedan discrepar.
Autenticar sin el botón
import { useAndco } from "@andco/sdk-react";
const andco = useAndco();
await andco.auth.signIn({ scopes: ["openid", "email"] });
await andco.auth.signOut();Llamar a la API
andco.rest.http es un cliente tipado contra el contrato OpenAPI: la ruta se valida al compilar y data llega con la forma que declara el esquema.
const andco = useAndco();
const [accounts, setAccounts] = useState<{ id: string; name: string }[] | null>(null);
useEffect(() => {
let alive = true;
void andco.rest.http.GET("/accounts").then(({ data, error }) => {
if (alive && !error) setAccounts(data.data);
});
return () => {
alive = false;
};
}, [andco]);No hay un hook para esto a propósito. Un useEffect con el cliente del contexto es tan corto como un hook dedicado y no te obliga a aprender otra API.
Un fallo llega como error, nunca lanzado: es un AndcoAPIError con code para ramificar, status, y response por si necesitas las cabeceras. Un corte de red produce el mismo error, con status en undefined.
Con TanStack Query
Cuando ya usas TanStack Query, no hace falta envolver nada. andco.rest.http es un cliente de openapi-fetch, así que openapi-react-query lo toma tal cual y genera hooks tipados desde el mismo contrato:
npm install @tanstack/react-query openapi-react-queryimport type { AndCoRestPaths } from "@andco/protocol/transport";
import { useAndco } from "@andco/sdk-react";
import createQueryClient from "openapi-react-query";
import { useMemo } from "react";
export function Accounts() {
const andco = useAndco();
// `createQueryClient` es una factory de closures sin caché propia, así que reconstruirla al
// cambiar la Identidad autorizada no descarta nada: la caché vive en el QueryClient de TanStack.
const $api = useMemo(() => createQueryClient<AndCoRestPaths>(andco.rest.http), [andco]);
const accounts = $api.useQuery("get", "/accounts");
if (accounts.isLoading) return <Skeleton />;
if (accounts.error) return <p>{accounts.error.message}</p>;
return <List accounts={accounts.data.data} />;
}AndCoRestPaths es obligatorio: TypeScript no puede deducir el mapa de rutas a partir de las firmas genéricas de un cliente, así que hay que nombrarlo.
El useMemo tampoco es opcional, pero fíjate en la dependencia: andco.rest, no andco. useAndco() devuelve una referencia nueva en cada cambio de Identidad Autorizada — inicio de sesión, cierre de sesión, un Grant ampliado — mientras que rest es la misma superficie antes y después de iniciar sesión. Memorizar sobre andco reconstruiría el cliente de consultas en cada inicio de sesión sin necesidad.
El error del hook viene tipado desde el contrato — error, required_scope, message. En ejecución es un AndcoAPIError; si necesitas code, status o response, redúcelo con error instanceof AndcoAPIError.
Monta QueryClientProvider por fuera de AndcoProvider. La caché es asunto de tu aplicación, no del SDK, y anidarla adentro sugiere que Andco la exige.
Mostrar un fallo del callback
useEffect(() => {
void andco.session.ready.then(({ error }) => {
if (error) setMessage(error.message);
});
}, [andco]);Una vuelta de callback que falla ocurre antes de que tu código llame a nada. Sin esto se ve igual que no tener sesión.
