@nylas/react wraps the same OAuth client as @nylas/connect in React idioms: a useNylasConnect hook that holds connection state, and a NylasConnectButton component that starts the flow. You get the drop-in OAuth flow and the option to keep addressing users by your own IDs, without managing a client instance across renders yourself.
New to this? The quickstart walks through a working setup and compares the 3 ways to run it.
Install the library
Section titled “Install the library”@nylas/react is published on npm and works with React 18 and 19. Install it instead of @nylas/connect, not alongside it, because the connect entry point re-exports the core client for you.
npm install @nylas/reactpnpm add @nylas/reactImport the auth pieces from the /connect subpath. The package root exports only the Scheduler and Notetaker components, so useNylasConnect and NylasConnectButton are not reachable from @nylas/react on its own.
import { useNylasConnect, NylasConnectButton } from "@nylas/react/connect";Connect a mailbox with the hook
Section titled “Connect a mailbox with the hook”useNylasConnect takes the same configuration object as the core client and returns connection state alongside the actions that change it. Call it once near the top of the tree that needs mailbox access; the hook creates and reuses a single client instance internally.
import { useNylasConnect } from "@nylas/react/connect";
function ConnectMailbox() { const { isConnected, grant, isLoading, error, connect } = useNylasConnect({ clientId: import.meta.env.VITE_NYLAS_CLIENT_ID, redirectUri: window.location.origin + "/auth/callback", });
if (isLoading) return <p>Checking connection…</p>; if (error) return <p>Error: {error.message}</p>; if (isConnected && grant) return <p>Connected as {grant.email}</p>;
return <button onClick={() => connect({ method: "popup" })}>Connect</button>;}The hook returns 4 state values (isConnected, grant, isLoading, error) and 5 actions (connect, logout, refreshSession, subscribe, setLogLevel), plus connectClient for the underlying instance. Full signatures are on the useNylasConnect reference.
Keep your own user IDs
Section titled “Keep your own user IDs”Pass identityProviderToken and the resulting grant links to the sub claim in your identity provider’s JWT, so you address mailboxes as /v3/grants/me with your existing user ID instead of storing a grant_id.
import { useAuth0 } from "@auth0/auth0-react";import { useNylasConnect } from "@nylas/react/connect";
function ConnectMailbox() { const { getAccessTokenSilently } = useAuth0();
const { connect } = useNylasConnect({ clientId: import.meta.env.VITE_NYLAS_CLIENT_ID, redirectUri: window.location.origin + "/auth/callback", identityProviderToken: async () => getAccessTokenSilently(), });
return <button onClick={() => connect({ method: "popup" })}>Connect</button>;}Wrap your app in your provider’s React provider (Auth0Provider, ClerkProvider, AuthKitProvider) so the token getter is available where the hook runs. There are 4 provider-specific walkthroughs in the React identity provider guides, and the tradeoffs of this approach are in use your own user IDs instead of grant IDs.
Use the prebuilt button
Section titled “Use the prebuilt button”NylasConnectButton renders a styled button that starts the flow, so you skip wiring onClick and the loading state yourself. It accepts the same method values as connect() and ships its own CSS, which the /connect entry point loads automatically.
import { NylasConnectButton } from "@nylas/react/connect";
function App() { return ( <NylasConnectButton clientId={import.meta.env.VITE_NYLAS_CLIENT_ID} redirectUri={window.location.origin + "/auth/callback"} method="popup" onSuccess={(result) => console.log("Connected:", result.grantInfo?.email)} /> );}Every prop is listed on the NylasConnectButton reference. Use the hook instead when you need your own markup or the connection state elsewhere in the tree.
Connect a mailbox with a redirect
Section titled “Connect a mailbox with a redirect”The inline method navigates the browser to the provider rather than opening a window, which is the safer choice on mobile and anywhere popups get blocked. connect() resolves to a URL string in this mode instead of a result object, so you perform the navigation.
const handleConnect = async () => { const authUrl = await connect({ method: "inline" }); window.location.href = authUrl as string;};The cast is needed because connect() returns AuthResult | string across both methods. Both produce the same grant.
Handle the OAuth callback
Section titled “Handle the OAuth callback”With the default autoHandleCallback: true, the hook detects the code and state parameters on mount and completes the exchange, so a callback route often needs no code beyond rendering. Reach for connectClient.callback() when you want to control what happens after it resolves.
import { useEffect, useState } from "react";import { useNylasConnect } from "@nylas/react/connect";
export default function AuthCallback() { const { connectClient } = useNylasConnect(config); const [error, setError] = useState<string | null>(null);
useEffect(() => { if (!connectClient) return; connectClient .callback() .then(() => { window.location.href = "/dashboard"; }) .catch((err) => setError(err.message)); }, [connectClient]);
return error ? <p>Authentication failed: {error}</p> : <p>Finishing…</p>;}To exchange the code on your own server instead, set autoHandleCallback: false and follow handling the OAuth callback on your backend.
Handle connection errors
Section titled “Handle connection errors”The hook surfaces failures on its error value rather than throwing, so a render can react to them directly. connect() still rejects, which lets you distinguish a failed attempt from a bad stored session.
function ConnectMailbox() { const { connect, error } = useNylasConnect(config); const [attemptError, setAttemptError] = useState<string | null>(null);
const handleConnect = async () => { setAttemptError(null); try { await connect({ method: "popup" }); } catch (err: any) { setAttemptError( err.name === "PopupError" ? "Popup was blocked. Allow popups, or use the redirect method." : err.message, ); } };
const message = error?.message ?? attemptError; return ( <div> {message && <p role="alert">{message}</p>} <button onClick={handleConnect}>Connect</button> </div> );}A blocked popup is the most common failure, and it’s the one case worth handling explicitly: fall back to the inline method rather than leaving the user on a button that appears inert. The underlying client defines 15 error types, listed in the @nylas/connect overview.
What’s next
Section titled “What’s next”useNylasConnectreference documents all 4 state values, 5 actions, and the React-only options such asautoRefreshIntervalandretryAttemptsNylasConnectButtonreference lists every prop and styling hook- React identity provider guides cover Auth0, Clerk, Google, and WorkOS
@nylas/connectlibrary documents the core client, including all 11 configuration options- Email API and Calendar API are what you call once a mailbox is connected