Nhost React Native 快速上手:基于 Expo 与 `@nhost/nhost-js` 构建 GraphQL 后端应用
Nhost React Native 快速上手基于 Expo 与nhost/nhost-js构建 GraphQL 后端应用【免费下载链接】nhostThe Open Source Firebase Alternative with GraphQL.项目地址: https://gitcode.com/GitHub_Trending/nh/nhost本文以仓库中 examples/quickstarts/reactnative 这个由create-expo-app生成的 Expo 项目为起点系统讲解如何在 React NativeExpo应用中接入 Nhost——一个开源的 Firebase 替代方案提供认证、GraphQL 数据库与文件存储。读者将掌握Nhost 客户端的初始化与配置、Expo 开发环境的启动与调试方式并结合仓库内配套的 React Native 教程示例 理解登录鉴权、会话持久化与 GraphQL 增删改查的完整链路最终能够把现有 Expo 项目改造成一套带后端能力的跨平台应用。关联文档定位一个 Expo 模板项目的标准 READMEexamples/quickstarts/reactnative/README.md是 Nhost 官方仓库中 React Native 快速起步模板自带的说明文件全文围绕如何运行一个由create-expo-app生成的 Expo 项目展开包含依赖安装、启动命令、可选的运行目标、重置项目脚本以及后续学习资源。需要说明的是该 README 本身是 Expo 脚手架生成的通用模板其中包含的 expo.dev 等外部链接仅用于指引通用 Expo 开发流程本文不做展开但它所描述的项目已被 Nhost 仓库改造为接入了 Nhost 客户端的实际示例因此本文将以该 README 的操作流程为主线结合仓库源码把运行起来之后如何与 Nhost 后端打通这一层补全。项目结构速览在动手运行之前先认识一下这个 quickstart 模板的目录结构完整清单见 examples/quickstarts/reactnativereactnative/ ├── app/ # expo-router 文件路由目录 │ ├── (tabs)/ # 底部标签页index / explore │ ├── not-found.tsx │ └── _layout.tsx ├── components/ # UI 组件ThemedText、ParallaxScrollView 等 ├── constants/ # Colors.ts 主题色 ├── hooks/ # useColorScheme、useThemeColor 等 ├── lib/ │ └── nhost.js # ★ Nhost 客户端初始化本模板与 Nhost 的接入点 ├── assets/ # 图标、字体、启动图 ├── scripts/reset-project.js ├── app.json # Expo 应用配置 └── package.json关键差异点在于lib/nhost.js——这是模板中唯一与 Nhost 相关的文件也是从通用 Expo 模板升级为Nhost 示例的桥梁我们会在后文重点解读。第一步安装依赖README 给出的安装命令是npm install需要注意的是本仓库是一个 pnpm workspace 单体仓库根目录存在 pnpm-workspace.yamlquickstart 项目的package.json中通过nhost/nhost-js: workspace:^直接引用了仓库内的 Nhost JS SDK 源码包见 examples/quickstarts/reactnative/package.json而不是发布到 npm 的独立版本。因此若在仓库内直接运行推荐使用与仓库一致的包管理器仓库根目录提供 pnpm-lock.yaml若要在自己的独立 Expo 项目中复刻该模板则改为安装 npm 发布的版本npm install nhost/nhost-js。模板依赖的核心版本以当前仓库锁定的版本为准expo ~53.0.27、react-native 0.79.6、react 19.0.0、expo-router ~5.1.11、nhost/nhost-jsworkspace 源码。这些版本意味着模板默认启用了 Expo 的新架构app.json中newArchEnabled: true与 expo-router 的文件路由。第二步启动应用依赖安装完成后运行npx expo start启动后终端输出会列出可用的打开方式运行目标说明development build通过npx expo run:android/npx expo run:ios构建的原生开发构建适合使用需要原生模块的完整能力Android emulator按a键在 Android 模拟器中打开需要 Android Studio 模拟器iOS simulator按i键在 iOS 模拟器中打开仅 macOSExpo Go手机扫码在 Expo Go 沙箱中预览是快速体验的受限环境此外package.json还提供了平台直达脚本npm run android、npm run ios、npm run web分别对应expo start --android/--ios/--web。模板采用file-based routing文件路由app目录下的每个文件对应一个页面app/(tabs)/index.tsx是首页、app/(tabs)/explore.tsx是探索页、app/not-found.tsx是 404 兜底页导航结构由app/_layout.tsx与app/(tabs)/_layout.tsx声明。模板的应用级配置集中在 app.json应用名为my-reactnative-appscheme为myreactnativeapp用于深链并配置了expo-router、expo-splash-screen两个插件与typedRoutes实验特性。重置为空白项目模板自带的示例代码tab 页、主题组件等需要清空时运行npm run reset-project该命令会把起始代码移动到app-example目录并生成一个空白的app目录供你从头开发脚本实现见 scripts/reset-project.js。重置后即可把 Nhost 相关代码放入新结构中。让模板真正连接 Nhost解读lib/nhost.jsREADME 没有提及 Nhost 接入但模板已经内置了连接后端的关键一行。查看 lib/nhost.jsimport { createClient } from nhost/nhost-js; export const nhost createClient({ subdomain: local, region: local, })要点拆解createClient来自nhost/nhost-js包SDK 主入口定义见 packages/nhost-js/src/index.ts客户端实现见 packages/nhost-js/src/nhost.ts调用后返回一个聚合了auth、graphql、storage、functions等子模块的NhostClient实例subdomain与region都设置为local表示连接本地的 Nhost CLI 开发环境https://local.auth.local.nhost.run之类的本地端点由 CLI 映射若连接云端项目需替换为控制台创建项目后得到的真实subdomain与region客户端实例通常在应用顶层通过模块导出或 Context 提供模板以模块导出的形式暴露供所有页面复用同一个实例。从 SDK 源码看createClient支持的常用配置还包括authUrl、graphqlUrl、storageUrl、functionsUrl、start是否启动时自动初始化、autoRefreshToken、autoSignIn、clientStorage/clientStorageType会话存储后端等具体选项可查阅 packages/nhost-js/src/nhost.ts。注意当前模板这份最简配置没有提供会话存储后端若在真实的 React Native 应用中需要登录态持久化应参考下一节给出的完整做法。进阶从 quickstart 到完整登录鉴权应用如果希望把 quickstart 扩展成带注册/登录/受保护页面的真实应用仓库内的 examples/tutorials/nhost-reactnative-tutorial 提供了比 quickstart 更完整的参考实现其核心要点可直接借鉴。1. 用 AsyncStorage 持久化会话nhost/nhost-js的会话存储后端接口SessionStorageBackend要求实现get/set/remove三个同步方法。React Native 的AsyncStorage是异步 API教程通过内存缓存 异步落盘的方式做了兼容见 app/lib/nhost/AsyncStorage.tsximport { DEFAULT_SESSION_KEY, type SessionStorageBackend, type StoredSession } from nhost/nhost-js/session; import AsyncStorage from react-native-async-storage/async-storage; export default class NhostAsyncStorage implements SessionStorageBackend { private key: string; private cache: StoredSession | null null; constructor(key: string DEFAULT_SESSION_KEY) { this.key key; this.loadFromAsyncStorage(); // 构造时立即尝试从 AsyncStorage 读取 } get(): StoredSession | null { return this.cache; // 同步返回内存缓存 } set(value: StoredSession): void { this.cache value; // 先更新内存再异步写入 AsyncStorage void (async () { try { await AsyncStorage.setItem(this.key, JSON.stringify(value)); } catch (error) { console.warn(Error saving session to AsyncStorage:, error); } })(); } remove(): void { this.cache null; void (async () { try { await AsyncStorage.removeItem(this.key); } catch (error) { console.warn(Error removing session from AsyncStorage:, error); } })(); } }这套实现的关键在于会话读取路径保持同步避免破坏 SDK 内部时序而写入路径异步化并全部加上try/catch兜底。2. AuthProvider 与登录页教程用 React Context 封装认证状态见 app/lib/nhost/AuthProvider.tsx核心逻辑包括通过expo-constants的Constants.expoConfig?.extra读取NHOST_SUBDOMAIN/NHOST_REGION未配置时回退到local把环境配置与代码解耦createClient({ subdomain, region, storage: new NhostAsyncStorage() })注入持久化存储启动时等待约 100ms 让 AsyncStorage 完成读取再调用nhost.getUserSession()恢复会话订阅nhost.sessionStorage.onChange(...)监听会话变化实现跨页面/跨设备同步对外暴露user、session、isAuthenticated、isLoading、nhost五个字段并提供useAuth()hook在 Provider 外使用会抛错。登录页 app/signin.tsx 展示了最常用的邮箱密码登录调用const response await nhost.auth.signInEmailPassword({ email, password }); // 拿到 session 即登录成功 if (response.body?.session) { router.replace(/profile); } else { setError(Failed to sign in. Please check your credentials.); }该教程还支持 Apple 登录app/components/AppleSignInButton.tsx依赖expo-apple-authentication以及注册、邮箱验证等流程对应页面见 app/signup.tsx、app/verify.tsx。3. 通过nhost.graphql.request完成数据增删改查认证打通后即可用nhost.graphql访问 Hasura GraphQL API。教程的待办列表页 app/todos.tsx 是一个完整的 CRUD 参考核心模式如下。查询自动带上登录用户的 JWTHasura 权限会按user_id过滤数据const response await nhost.graphql.requestGetTodos({ query: query GetTodos { todos(order_by: { created_at: desc }) { id title details completed created_at updated_at user_id } } , });插入user_id由 Hasura 根据 JWT 自动填充无需客户端传const response await nhost.graphql.requestInsertTodo({ query: mutation InsertTodo($title: String!, $details: String) { insert_todos_one(object: { title: $title, details: $details }) { id title details completed created_at updated_at user_id } } , variables: { title: newTodoTitle.trim(), details: newTodoDetails.trim() || null }, });更新与删除使用update_todos_by_pk/delete_todos_by_pk按主键操作Hasura permissions保证用户只能改删自己的数据。每次请求后都需检查response.body.errors并统一处理异常。常见问题与调试建议本地后端如何启动subdomain: local依赖 Nhost CLI 在本地拉起完整的 Nhost 环境Auth、Hasura、Postgres、Storage。可参考 examples/quickstarts/reactnative/nhost 目录下的配置当前 quickstart 中该目录主要存放后端迁移/种子数据在项目根执行 Nhost CLI 的nhost dev即可提供本地端点云环境则需替换 subdomain/region。会话恢复为空优先检查是否实现了SessionStorageBackend并传入createClient的storage选项同时确认登录接口返回了session字段。GraphQL 请求 401/403确认客户端初始化时 subdomain/region 正确、JWT 已随请求附加SDK 通过 packages/nhost-js/src/fetch/middlewareAttachAccessToken.ts 这类 fetch 中间件自动附加 token并核对 Hasura 的权限规则。TypeScript 类型nhost.graphql.requestT支持传入响应类型泛型教程中GetTodos、InsertTodo等接口即为此用途可减少运行时错误。小结从 README.md 的装依赖、起服务两步走到接入 lib/nhost.js 的客户端初始化再到参考 nhost-reactnative-tutorial 补齐 AsyncStorage 会话持久化、AuthProvider 登录态管理、GraphQL CRUD 三个关键模块一条完整的Nhost × React Native开发链路就此打通。Quickstart 模板提供的是脚手架起点而仓库中的教程示例则是把脚手架变成真实业务应用的实战范本两者结合使用即可快速搭建基于 Expo 的跨平台全栈应用。【免费下载链接】nhostThe Open Source Firebase Alternative with GraphQL.项目地址: https://gitcode.com/GitHub_Trending/nh/nhost创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考