# 客户端 (/docs/concepts/client)

了解如何为 React、Vue、Svelte 和其他框架设置 Better Auth 客户端、使用钩子、配置 fetch 选项、处理错误，以及通过客户端插件进行扩展。



Better Auth 提供了一个与流行前端框架（如 React、Vue、Svelte 等）兼容的客户端库。该客户端库包含一组用于与 Better Auth 服务器交互的函数。每个框架的客户端库都建立在一个与框架无关的核心客户端库之上，因此所有方法和钩子在所有客户端库中均保持一致。

## 安装 [#安装]

如果尚未安装，请先安装 better-auth。

<CodeBlockTabs defaultValue="npm" groupId="persist-install">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npm i better-auth
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm add better-auth
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn add better-auth
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun add better-auth
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## 创建客户端实例 [#创建客户端实例]

从你所用的框架的包中导入 `createAuthClient`（例如 React 框架使用 "better-auth/react"）。调用该函数创建你的客户端。传入你身份验证服务器的基础 URL。如果身份验证服务器与客户端运行在同一域上，则可以跳过此步骤。

<Callout type="info">
  如果你的身份验证服务器使用的基础路径不是 `/api/auth`，你可以传入包含路径的完整 URL（例如 `http://localhost:3000/custom-path/auth`），也可以单独使用 `basePath` 选项
</Callout>

<Tabs items="[&#x22;react&#x22;, &#x22;vue&#x22;, &#x22;svelte&#x22;, &#x22;solid&#x22;, &#x22;vanilla&#x22;]" defaultValue="react">
  <Tab value="vanilla">
    ```ts title="lib/auth-client.ts" 
    import { createAuthClient } from "better-auth/client" // [!code highlight]
    export const authClient = createAuthClient({
        baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
    })
    ```
  </Tab>

  <Tab value="react" title="lib/auth-client.ts">
    ```ts title="lib/auth-client.ts"  
    import { createAuthClient } from "better-auth/react" // [!code highlight]
    export const authClient = createAuthClient({
        baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
    })
    ```
  </Tab>

  <Tab value="vue" title="lib/auth-client.ts">
    ```ts title="lib/auth-client.ts" 
    import { createAuthClient } from "better-auth/vue" // [!code highlight]
    export const authClient = createAuthClient({
        baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
    })
    ```
  </Tab>

  <Tab value="svelte" title="lib/auth-client.ts">
    ```ts title="lib/auth-client.ts" 
    import { createAuthClient } from "better-auth/svelte" // [!code highlight]
    export const authClient = createAuthClient({
        baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
    })
    ```
  </Tab>

  <Tab value="solid" title="lib/auth-client.ts">
    ```ts title="lib/auth-client.ts" 
    import { createAuthClient } from "better-auth/solid" // [!code highlight]
    export const authClient = createAuthClient({
        baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
    })
    ```
  </Tab>
</Tabs>

## 使用方法 [#使用方法]

创建客户端实例后，你可以使用该客户端与 Better Auth 服务器交互。客户端默认提供一组函数，也可以使用插件进行扩展。

**示例：登录**

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"
const authClient = createAuthClient()

await authClient.signIn.email({
    email: "test@user.com",
    password: "password1234"
})
```

### 钩子 [#钩子]

除了标准方法外，客户端还提供钩子，以便轻松访问不同的响应式数据。每个钩子都可以在客户端根对象中使用，且名称都以 `use` 开头。

**示例：useSession**

<Tabs items="[&#x22;React&#x22;, &#x22;Vue&#x22;,&#x22;Svelte&#x22;, &#x22;Solid&#x22;]" defaultValue="react">
  <Tab value="React">
    ```tsx title="user.tsx"
    //make sure you're using the react client
    import { createAuthClient } from "better-auth/react"
    const { useSession } = createAuthClient() // [!code highlight]

    export function User() {
        const {
            data: session,
            isPending, //loading state
            error, //error object 
            refetch //refetch the session
        } = useSession()
        return (
            //...
        )
    }
    ```
  </Tab>

  <Tab value="Vue">
    ```vue title="user.vue"
    <script lang="ts" setup>
    import { authClient } from '@/lib/auth-client'
    const session = authClient.useSession()
    </script>
    <template>
        <div>
            <button v-if="!session.data" @click="() => authClient.signIn.social({
                provider: 'github'
            })">
                Continue with GitHub
            </button>
            <div>
                <pre>{{ session.data }}</pre>
                <button v-if="session.data" @click="authClient.signOut()">
                    Sign out
                </button>
            </div>
        </div>
    </template>
    ```
  </Tab>

  <Tab value="Svelte">
    ```svelte title="user.svelte"
    <script lang="ts">
    import { authClient } from "$lib/auth-client";
    const session = authClient.useSession();
    </script>

    <div
        style="display: flex; flex-direction: column; gap: 10px; border-radius: 10px; border: 1px solid #4B453F; padding: 20px; margin-top: 10px;"
    >
        <div>
        {#if $session.data}
            <div>
            <p>
                {$session.data.user.name}
            </p>
            <p>
                {$session.data.user.email}
            </p>
            <button
                onclick={async () => {
                await authClient.signOut();
                }}
            >
                Signout
            </button>
            </div>
        {:else}
            <button
            onclick={async () => {
                await authClient.signIn.social({
                provider: "github",
                });
            }}
            >
            Continue with GitHub
            </button>
        {/if}
        </div>
    </div>
    ```
  </Tab>

  <Tab value="Solid">
    ```tsx title="user.tsx"
    import { authClient } from "~/lib/auth-client";
    import { Show } from 'solid-js';

    export default function Home() {
        const session = authClient.useSession()
        return (
            <Show
                when={session()}
                fallback={<button onClick={toggle}>Log in</button>}
            >
                <button onClick={toggle}>Log out</button>
            </Show>
        ); 
    }
    ```
  </Tab>
</Tabs>

### 请求选项 [#请求选项]

客户端使用一个名为 [better fetch](https://better-fetch.vercel.app) 的库向服务器发出请求。

Better fetch 是对原生 fetch API 的封装，提供了更方便的请求方式。它由 Better Auth 团队创建，设计上与 Better Auth 无缝配合。

你可以通过向 `createAuthClient` 传递 `fetchOptions` 对象，为客户端设置默认的 fetch 选项。

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"

const authClient = createAuthClient({
    fetchOptions: {
        // 任何 better-fetch 的选项
    },
})
```

### 禁用默认的 Fetch 插件 [#禁用默认的-fetch-插件]

身份验证客户端包含默认的 fetch 插件，用于处理浏览器特有的行为，比如自动重定向。对于非浏览器环境（例如 React Native/Expo），你可以通过将 `disableDefaultFetchPlugins` 设置为 `true` 来禁用这些插件：

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"

const authClient = createAuthClient({
    disableDefaultFetchPlugins: true,
})
```

你也可以将 fetch 选项传递给大多数客户端函数，作为第二个参数，或者作为对象中的属性。

```ts
import { authClient } from "@/lib/auth-client"

await authClient.signIn.email({
    email: "email@email.com",
    password: "password1234",
}, {
    onSuccess(ctx) {
            //      
    }
})

//或

await authClient.signIn.email({
    email: "email@email.com",
    password: "password1234",
    fetchOptions: {
        onSuccess(ctx) {
            //      
        }
    },
})
```

### 会话选项 [#会话选项]

你可以使用 `sessionOptions` 选项配置客户端处理会话获取和重新验证的方式。

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"

const authClient = createAuthClient({
    sessionOptions: {
        refetchInterval: 0,
        refetchOnWindowFocus: true,
        refetchWhenOffline: false,
    }
})
```



<TypeTable type="clientSessionOptionsType" />

### 禁用默认 Fetch 插件 [#禁用默认-fetch-插件]

客户端包含一个默认的重定向插件，用于处理身份验证重定向。如果你需要禁用此行为，可以将 `disableDefaultFetchPlugins` 设置为 `true`。

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"

const authClient = createAuthClient({
    disableDefaultFetchPlugins: true
})
```

### 禁用钩子重新渲染 [#禁用钩子重新渲染]

某些端点在成功响应后，会触发 atom 信号，导致像 `useSession` 的钩子重新渲染。
这对于让你的 UI 与身份验证状态保持同步非常有用。

但是，有时你可能想要调用端点而不触发钩子重新渲染。
例如，更新不会影响 session 的用户偏好时，或者你想手动控制钩子何时更新。

你可以通过在 fetch 选项中设置 `disableSignal: true`，禁用特定端点调用的钩子重新渲染：

```ts
import { authClient } from "@/lib/auth-client"

// 作为第二个参数
await authClient.updateUser({
    name: "New Name"
}, {
    disableSignal: true
})

// 或者在 fetchOptions 中
await authClient.updateUser({
    name: "New Name",
    fetchOptions: {
        disableSignal: true
    }
})
```

当 `disableSignal` 设置为 `true` 时，端点调用会成功完成，
但像 `useSession` 这样的钩子不会自动重新渲染。你可以根据需要手动触发重新获取：

```ts
import { authClient } from "@/lib/auth-client"

const { refetch } = authClient.useSession()

await authClient.updateUser({
    name: "New Name"
}, {
    disableSignal: true,
    onSuccess() {
        // 如果需要，手动重新获取 session
        refetch()
    }
})
```

### 错误处理 [#错误处理]

大多数客户端函数都会返回一个包含以下属性的响应对象：

* `data`：响应数据
* `error`：如果发生错误，则为错误对象

错误对象包含以下属性：

* `message`：错误消息（例如：“Invalid email or password”）
* `status`：HTTP 状态码
* `statusText`：HTTP 状态文本

```ts
import { authClient } from "@/lib/auth-client"

const { data, error } = await authClient.signIn.email({
    email: "email@email.com",
    password: "password1234"
})
if (error) {
    // 处理错误
}
```

如果动作支持 `fetchOptions` 选项，你可以传入 `onError` 回调来处理错误。

```ts
import { authClient } from "@/lib/auth-client"

await authClient.signIn.email({
    email: "email@email.com",
    password: "password1234",
}, {
    onError(ctx) {
        // 处理错误
    }
})

// 或者
await authClient.signIn.email({
    email: "email@email.com",
    password: "password1234",
    fetchOptions: {
        onError(ctx) {
            // 处理错误
        }
    }
})
```

像 `useSession` 这样的钩子也会返回错误对象（如果获取 session 失败），此外还返回 `isPending` 属性以指示请求是否仍在进行中。

```ts
import { useSession } from "@/lib/auth-client"

const { data, error, isPending } = useSession()
if (error) {
    // 处理错误
}
```

#### 错误代码 [#错误代码]

客户端实例包含 `$ERROR\_CODES` 对象，其中包含服务器返回的所有错误代码。你可以使用它来处理错误翻译或自定义错误消息。

```ts title="auth-client.ts"
const authClient = createAuthClient();

type ErrorTypes = Partial<
	Record<
		keyof typeof authClient.$ERROR_CODES,
		{
			en: string;
			es: string;
		}
	>
>;

const errorCodes = {
	USER_ALREADY_EXISTS: {
		en: "user already registered",
		es: "usuario ya registrado",
	},
} satisfies ErrorTypes;

const getErrorMessage = (code: string, lang: "en" | "es") => {
	if (code in errorCodes) {
		return errorCodes[code as keyof typeof errorCodes][lang];
	}
	return "";
};


const { error } = await authClient.signUp.email({
	email: "user@email.com",
	password: "password",
	name: "User",
});
if(error?.code){
    alert(getErrorMessage(error.code, "en"));
}
```

### SSR 水合 [#ssr-水合]

对于 Next.js、Nuxt 或 SvelteKit 等 SSR 框架，`useSession` 会在客户端获取 session，从而导致加载闪烁。将服务器获取的 session 传递给 `hydrateSession` 并将其用作回退值，这样首次渲染时服务器和客户端都有数据：

```tsx title="page.tsx (server component)"
import { auth } from "@/lib/auth"
import { headers } from "next/headers"
import { SessionCard } from "./session-card"

export default async function Page() {
    const session = await auth.api.getSession({
        headers: await headers(),
    })
    return <SessionCard initialSession={session} />
}
```

```tsx title="session-card.tsx (client component)"
"use client"

import { authClient } from "@/lib/auth-client"

type Props = {
    initialSession: typeof authClient.$Infer.Session | null
}

export function SessionCard({ initialSession }: Props) {
    authClient.hydrateSession(initialSession)
    const { data, isPending, isRefetching } = authClient.useSession()
    const session = isPending && !isRefetching ? initialSession : data

    if (!session) return <p>未登录</p>
    return <pre>{JSON.stringify(session, null, 2)}</pre>
}
```

<Callout>
  * 只有第一次传入非 null 值的 `hydrateSession` 调用会生效
  * 传入 `null` 是安全的。它会被忽略，`useSession` 将照常获取
</Callout>

在 React 中，`useSession` 和 `useListOrganizations` 等身份验证查询钩子会在服务器渲染和水合期间返回其初始待处理状态，然后更新为当前客户端状态。这样可以使流式传输组件与其服务器 HTML 保持一致，即使其他组件已经获取或水合了该查询也是如此。如上所示，继续使用服务器获取的 session 作为回退值，以便在水合期间显示它。不使用 `useAuthQuery` 的自定义插件存储会保留其现有的快照行为。

### 插件 [#插件]

你可以使用插件扩展客户端，以添加更多功能。插件可以向客户端添加新函数或修改现有函数。

**示例：Magic Link 插件**

```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"
import { magicLinkClient } from "better-auth/client/plugins"

const authClient = createAuthClient({
    plugins: [
        magicLinkClient()
    ]
})
```

添加插件后，你可以使用插件提供的新函数。

```ts
import { authClient } from "@/lib/auth-client"

await authClient.signIn.magicLink({
    email: "test@email.com"
})
```

