React Router v7 集成
将 Better Auth 集成到 React Router v7(原为 Remix)中。
Better Auth 可以轻松集成到 React Router v7。本指南将向您展示如何将 Better Auth 与 React Router v7 集成。
React Router v7 是 Remix 的后继版本。如果您使用的是 Remix v2,主要区别在于将导入从 @remix-run/* 更改为 react-router。API 保持不变。
您可以按照安装中的步骤开始,或者按照本指南以 React Router 的方式进行集成。
如果您已经完成了安装步骤,可以跳过第一步。
创建 auth 实例
在以下位置创建一个名为 auth.server.ts 的文件:
- 项目根目录
lib/文件夹utils/文件夹
您也可以将上述任意文件夹嵌套在 app/ 文件夹下(例如 app/lib/auth.server.ts)。
然后在该文件中,导入 Better Auth 并创建您的实例。
确保使用变量名 auth 或 default 导出该 auth 实例。
import { betterAuth } from "better-auth"
export const auth = betterAuth({
database: {
provider: "postgres", // 根据您的数据库提供者更改此处
url: process.env.DATABASE_URL, // 数据库路径或连接字符串
}
})创建 API 路由
我们需要将处理函数挂载到 API 路由中。在 app/routes/ 目录下创建资源路由文件 api.auth.$.ts,并添加以下代码:
React Router v7
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,唯一不同的是导入:
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)
}您可以在 Better Auth 配置中更改路径,但建议保持为 routes/api.auth.$.ts
创建客户端
在此处创建客户端实例。我们将在 lib/ 目录下创建 auth-client.ts 文件。
import { createAuthClient } from "better-auth/react" // 确保从 better-auth/react 导入
export const authClient = createAuthClient({
// 您可以在此传递客户端配置
})创建客户端后,您可以使用它进行注册、登录及其他操作。
使用示例
注册
React Router v7
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(旧版)
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
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(旧版)
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>
)
}