# React Router v7 集成 (/docs/integrations/react-router)

将 Better Auth 集成到 React Router v7（原为 Remix）中。



Better Auth 可以轻松集成到 React Router v7。本指南将向您展示如何将 Better Auth 与 React Router v7 集成。

<Callout type="info">
  React Router v7 是 Remix 的后继版本。如果您使用的是 Remix v2，主要区别在于将导入从 `@remix-run/*` 更改为 `react-router`。API 保持不变。
</Callout>

您可以按照[安装](/docs/installation)中的步骤开始，或者按照本指南以 React Router 的方式进行集成。

如果您已经完成了安装步骤，可以跳过第一步。

## 创建 auth 实例 [#创建-auth-实例]

在以下位置创建一个名为 `auth.server.ts` 的文件：

* 项目根目录
* `lib/` 文件夹
* `utils/` 文件夹

您也可以将上述任意文件夹嵌套在 `app/` 文件夹下（例如 `app/lib/auth.server.ts`）。

然后在该文件中，导入 Better Auth 并创建您的实例。

<Callout type="warn">
  确保使用变量名 `auth` 或 `default` 导出该 auth 实例。
</Callout>

```ts title="app/lib/auth.server.ts"
import { betterAuth } from "better-auth"

export const auth = betterAuth({
    database: {
        provider: "postgres", // 根据您的数据库提供者更改此处
        url: process.env.DATABASE_URL, // 数据库路径或连接字符串
    }
})
```

## 创建 API 路由 [#创建-api-路由]

我们需要将处理函数挂载到 API 路由中。在 `app/routes/` 目录下创建资源路由文件 `api.auth.$.ts`，并添加以下代码：

### React Router v7 [#react-router-v7]

```ts title="app/routes/api.auth.$.ts"
import { auth } from '~/lib/auth.server' // 根据需要调整路径
import type { LoaderFunctionArgs, ActionFunctionArgs } from "react-router"

export async function loader({ request }: LoaderFunctionArgs) {
    return auth.handler(request)
}

export async function action({ request }: ActionFunctionArgs) {
    return auth.handler(request)
}
```

### Remix v2（旧版） [#remix-v2旧版]

如果您仍在使用 Remix v2，唯一不同的是导入：

```ts title="app/routes/api.auth.$.ts"
import { auth } from '~/lib/auth.server' // 根据需要调整路径
import type { LoaderFunctionArgs, ActionFunctionArgs } from "@remix-run/node"

export async function loader({ request }: LoaderFunctionArgs) {
    return auth.handler(request)
}

export async function action({ request }: ActionFunctionArgs) {
    return auth.handler(request)
}
```

<Callout type="info">
  您可以在 Better Auth 配置中更改路径，但建议保持为 `routes/api.auth.$.ts`
</Callout>

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

在此处创建客户端实例。我们将在 `lib/` 目录下创建 `auth-client.ts` 文件。

```ts title="app/lib/auth-client.ts"
import { createAuthClient } from "better-auth/react" // 确保从 better-auth/react 导入

export const authClient = createAuthClient({
    // 您可以在此传递客户端配置
})
```

创建客户端后，您可以使用它进行注册、登录及其他操作。

### 使用示例 [#使用示例]

### 注册 [#注册]

#### React Router v7 [#react-router-v7-1]

```ts title="app/routes/signup.tsx"
import { Form } from "react-router"
import { useState } from "react"
import { authClient } from "~/lib/auth-client"

export default function SignUp() {
  const [email, setEmail] = useState("")
  const [name, setName] = useState("")
  const [password, setPassword] = useState("")

  const signUp = async () => {
    await authClient.signUp.email(
      {
        email,
        password,
        name,
      },
      {
        onRequest: (ctx) => {
          // 显示加载状态
        },
        onSuccess: (ctx) => {
          // 重定向到首页
        },
        onError: (ctx) => {
          alert(ctx.error)
        },
      },
    )
  }

  return (
    <div>
      <h2>
        注册
      </h2>
      <Form
        onSubmit={signUp}
      >
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="姓名"
        />
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="邮箱"
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="密码"
        />
        <button
          type="submit"
        >
          注册
        </button>
      </Form>
    </div>
  )
}
```

#### Remix v2（旧版） [#remix-v2旧版-1]

```ts title="app/routes/signup.tsx"
import { Form } from "@remix-run/react"
import { useState } from "react"
import { authClient } from "~/lib/auth-client"

export default function SignUp() {
  const [email, setEmail] = useState("")
  const [name, setName] = useState("")
  const [password, setPassword] = useState("")

  const signUp = async () => {
    await authClient.signUp.email(
      {
        email,
        password,
        name,
      },
      {
        onRequest: (ctx) => {
          // 显示加载状态
        },
        onSuccess: (ctx) => {
          // 重定向到首页
        },
        onError: (ctx) => {
          alert(ctx.error)
        },
      },
    )
  }

  return (
    <div>
      <h2>
        注册
      </h2>
      <Form
        onSubmit={signUp}
      >
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="姓名"
        />
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="邮箱"
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="密码"
        />
        <button
          type="submit"
        >
          注册
        </button>
      </Form>
    </div>
  )
}
```

### 登录 [#登录]

#### React Router v7 [#react-router-v7-2]

```ts title="app/routes/signin.tsx"
import { Form } from "react-router"
import { useState } from "react"
import { authClient } from "~/lib/auth-client"

export default function SignIn() {
  const [email, setEmail] = useState("")
  const [name, setName] = useState("")
  const [password, setPassword] = useState("")

  const signIn = async () => {
    await authClient.signIn.email(
      {
        email,
        password,
      },
      {
        onRequest: (ctx) => {
          // 显示加载状态
        },
        onSuccess: (ctx) => {
          // 重定向到首页
        },
        onError: (ctx) => {
          alert(ctx.error)
        },
      },
    )
  }

  return (
    <div>
      <h2>
        登录
      </h2>
      <Form
        onSubmit={signIn}
      >
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="姓名"
        />
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="邮箱"
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="密码"
        />
        <button
          type="submit"
        >
          登录
        </button>
      </Form>
    </div>
  )
}
```

### Remix v2（旧版） [#remix-v2旧版-2]

```ts title="app/routes/signin.tsx"
import { Form } from "@remix-run/react"
import { useState } from "react"
import { authClient } from "~/lib/auth-client"

export default function SignIn() {
  const [email, setEmail] = useState("")
  const [name, setName] = useState("")
  const [password, setPassword] = useState("")

  const signIn = async () => {
    await authClient.signIn.email(
      {
        email,
        password,
      },
      {
        onRequest: (ctx) => {
          // 显示加载状态
        },
        onSuccess: (ctx) => {
          // 重定向到首页
        },
        onError: (ctx) => {
          alert(ctx.error)
        },
      },
    )
  }

  return (
    <div>
      <h2>
        登录
      </h2>
      <Form
        onSubmit={signIn}
      >
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="姓名"
        />
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="邮箱"
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="密码"
        />
        <button
          type="submit"
        >
          登录
        </button>
      </Form>
    </div>
  )
}
```

