像 React 这样的现代前端框架让开发人员的状态管理变得更加容易,但是使用像 Convex 这样的解决方案进行状态管理却让它变得更加容易。在 React 中,组件的状态决定了 UI 的外观,虽然管理应用程序的状态变得相对简单,但全局状态概念仍然是开发人员的痛点。

例如,考虑跟踪与全局状态一起工作的金融交易的应用程序,所有客户端都可以实时更改和观察。此类应用程序很难开发,因为开发人员需要在应用程序之间同步状态并处理 ACID 属性。

Convex旨在通过提供包括数据存储、检索和突变在内的全栈解决方案来解决这个问题,所有这些都内置在用于全局状态管理的 SDK 中。它的无服务器方法是高效的,并且是一个高度可扩展的平台。Convex 是一个开发者优先的平台,其反应式架构与 React 非常吻合,并且 SDK 还支持乐观更新和订阅等功能。

在本教程中,我们将使用 Convex 构建一个全栈 Next.js 应用程序,用于全局状态管理。我们还将实现凸函数来查询和更新数据。在本教程结束时,我们将把最终的应用程序部署到 Vercel — 随时使用这个GitHub 存储库跟随本演练。

  • 设置 Next.js 项目

  • 设置凸

  • 使用 Convex 添加状态管理

    • 定义架构

    • 实现凸函数

    • 用凸函数连接组件

    • 管理凸

  • 保护应用程序

    • 创建 Auth0 应用程序

    • 设置 Auth0

    • 将 Auth0 与凸集成

  • 部署到 Vercel

先决条件

您需要在计算机上安装 Node.js、npm 或 yarn,以及像 VS Code 这样的代码编辑器。您还需要一个 GitHub 帐户才能与 Convex 一起使用。

设置 Next.js 项目

该应用程序将允许用户查看现有帖子的列表并提交新的博客帖子。一篇博文将包含标题、正文和作者姓名。

首先,运行以下命令来设置一个新的 Next.js 项目:

npx create-next-app@latest凸示例 --typescript

在代码编辑器中打开项目并更新pages/index.tsx文件以显示表单以创建博客文章:

// pages/index.tsx
从“下一个”导入类型 { NextPage }
从“下一个/头”导入头
从 '../styles/Home.module.css' 导入样式
从“反应”导入 { useCallback, useState }
​
常量主页:NextPage = () => {const [作者,setAuthor] = useState('')const [title, setTitle] = useState('')const [body, setBody] = useState('')
​常量 createPost = async () => {// TODO: 在数据库中创建一个新帖子console.log({作者、标题、正文})// 提交后重置输入设置作者('')集合体('')设置标题('')}
​返回 (<div className={styles.container}><头部><title>Next.js 凸面</title><meta name="description" content="由创建下一个应用生成" /><link rel="icon" href="/favicon.ico" /></头>
​<主类名={styles.main}><h1 className={styles.title}>欢迎使用{' '} 访问 <a href="https://nextjs.org">Next.js</a><a href="https://convex.dev">凸</a></h1><输入类型={'文本'}价值={标题}占位符={'标题'}className={styles.inputStyles}onChange={(event) => setTitle(event.target.value)}/>      <输入类型={'文本'}价值={作者}占位符={'作者'}className={styles.inputStyles}onChange={(event) => setAuthor(event.target.value)}/><文本区域价值={正文}行={5}placeholder={'帖子正文'}className={styles.inputStyles}onChange={(event) => setBody(event.target.value)}/><button className={styles.button} onClick={createPost}>创建帖子</按钮></main></div>)
}
​
导出默认主页

更新styles/Home.module.css如下:

/* 样式/Home.module.css */
。容器 {填充:0 2rem;显示:弯曲;弹性方向:列;
}
​
。主要的 {填充:4rem 0;弹性:10;显示:弯曲;弹性方向:列;证明内容:中心;对齐项目:居中;
}
​
。按钮 {字体大小:1rem;字体粗细:800;光标:指针;保证金:0.5rem;填充:0.5rem;文字装饰:无;边框:1px 实心#eaeaea;边框半径:10px;过渡:颜色 0.15s 缓动,边框颜色 0.15s 缓动;宽度:200px;
}
​
.button:悬停,
.button:焦点,
.按钮:活动{颜色:#0070f3;边框颜色:#0070f3;
}
​
.inputStyles {宽度:300px;边距:10px 自动;
}

运行npm run dev以启动应用程序,然后http://localhost:3000/在 Web 浏览器中打开。


超过 20 万开发人员使用 LogRocket 来创造更好的数字体验了解更多 →


创建新帖子的表格已准备就绪。现在,您必须实现使用 Convex 保存和读取数据的逻辑。

设置凸

Convex 提供了一个可以在项目中使用的 JavaScript SDK。

  1. 运行npm i convex安装凸包

  2. 在项目内部,运行npx convex login,这将在浏览器中打开一个页面,使用您的 GitHub 帐户登录 Convex

  3. 登录后,运行npx convex init以初始化 Convex 项目,convex.json并.env.local进行配置。此命令还将创建一个convex/目录以将函数写入

(注意:此命令将提示您输入项目名称)

最后,更新pages/_app.tsx以添加ConvexProvider到完整的应用程序中。这ConvexProvider将允许您在整个应用程序中使用 Convex 提供的 React 钩子。

// 页面/_app.tsx
导入'../styles/globals.css'
从“下一个/应用程序”导入类型 { AppProps }
​
从 'convex/react' 导入 { ConvexProvider, ConvexReactClient }
从'../convex.json'导入conveconfig
常量凸 = 新的 ConvexReactClient(convexConfig.origin)
​
功能 MyApp({ 组件, pageProps }: AppProps) {返回 (<ConvexProvider 客户端={convex}><组件 {...pageProps} /></ConvexProvider>)
}
​
导出默认 MyApp

使用 Convex 添加状态管理

在项目中设置 Convex 后,是时候创建数据模型并将前端与数据库连接起来了。

定义架构

在convex/文件夹中,创建一个新文件 ,schema.ts来定义博客文章的架构。该函数将在 Convex 内defineTable创建一个表。posts

// 凸/schema.ts
从'凸/模式'导入{defineSchema,defineTable,s}
​
导出默认defineSchema({帖子:定义表({标题:s.string(),作者:s.string(),正文:s.string(),}),
})

现在,运行npx convex codegen为posts模式生成类型定义以改进代码完成。这将允许您将帖子引用为Document<'posts'>.

实现凸函数

凸函数允许前端以两种方式与数据库通信:查询和变异。

这些函数是从目录中的文件导出的convex,它们被部署为无服务器函数以执行数据库交互。

前端需要阅读可用的帖子。为此,创建一个新文件;convex/getPosts.ts. 此文件导出一个查询函数,该函数返回posts数据库中的所有可用数据。

// 凸/getPosts.ts
从'./_generated/server'导入{查询}
从'./_generated/dataModel'导入{文档}
​
导出默认查询(异步({ db}):Promise<Document<'posts'>[]> => {返回等待 db.table('posts').collect()
})

在convex/文件夹中,创建一个名为addPost.ts. 该文件导出一个变异函数以允许用户向数据库添加新帖子。该函数接受一个post对象作为参数。

// 凸/addPost.ts
从'./_generated/server'导入{突变}
​
导出默认突变(异步 ({ D b },帖子:{作者:字符串;正文:字符串;标题:字符串}) => {等待 db.insert('posts', post)}
)

运行npx convex push以生成类型定义并将函数部署到 Convex。

来自 LogRocket 的更多精彩文章:

  • 不要错过来自 LogRocket 的精选时事通讯The Replay

  • 使用 React 的 useEffect优化应用程序的性能

  • 在多个 Node 版本之间切换

  • 了解如何使用 AnimXYZ 为您的 React 应用程序制作动画

  • 探索 Tauri,一个用于构建二进制文件的新框架

  • 比较NestJS 与 Express.js

  • 发现TypeScript 领域中使用的流行 ORM


用凸函数连接组件

Convex 提供useQuery并useMutation使用上面实现的功能与数据库交互的钩子。

将useMutation钩子添加到Home组件并更新createPost函数以使用发布数据调用addPost突变函数。

// pages/index.tsx
从“下一个”导入类型 { NextPage }
从“下一个/头”导入头
从 '../styles/Home.module.css' 导入样式
从“反应”导入 { useCallback, useState }
从“../convex/_generated/react”导入 {useMutation};
​
常量主页:NextPage = () => {const addPost = useMutation('addPost')
​const [作者,setAuthor] = useState('')const [title, setTitle] = useState('')const [body, setBody] = useState('')
​常量 createPost = async () => {等待 addPost({ 正文, 作者, 标题});// 提交后重置输入设置作者('')集合体('')设置标题('')}
​返回 (// 返回组件)
}
​
导出默认主页

添加useQuery挂钩以从数据库中获取和显示帖子列表。useQuery钩子将在加载数据时返回,undefined之后会返回一个帖子列表。

// pages/index.tsx
从“下一个”导入类型 { NextPage }
从“下一个/头”导入头
从 '../styles/Home.module.css' 导入样式
从“反应”导入 { useCallback, useState }
从“../convex/_generated/react”导入 {useMutation, useQuery};
​
常量主页:NextPage = () => {常量帖子 = useQuery('getPosts')const addPost = useMutation('addPost')
​const [作者,setAuthor] = useState('')const [title, setTitle] = useState('')const [body, setBody] = useState('')
​常量 createPost = async () => {等待 addPost({ 正文, 作者, 标题});// 提交后重置输入设置作者('')集合体('')设置标题('')}
​返回 (<div className={styles.container}><头部><title>Next.js 凸面</title><meta name="description" content="由创建下一个应用生成" /><link rel="icon" href="/favicon.ico" /></头>
​<主类名={styles.main}><h1 className={styles.title}>欢迎使用{' '} 访问 <a href="https://nextjs.org">Next.js</a><a href="https://convex.dev">凸</a></h1>{帖子?(<><p className={styles.description}>{'帖子总数:'} {posts.length}</p>
​<ul>{posts.map((post) => (<li key={post._id.toString()}>{post.title}</li>))}</ul></>) : ('正在加载帖子...')}<输入类型={'文本'}价值={标题}占位符={'标题'}className={styles.inputStyles}onChange={(event) => setTitle(event.target.value)}/>      <输入类型={'文本'}价值={作者}占位符={'作者'}className={styles.inputStyles}onChange={(event) => setAuthor(event.target.value)}/><文本区域价值={正文}行={5}placeholder={'帖子正文'}className={styles.inputStyles}onChange={(event) => setBody(event.target.value)}/><button className={styles.button} onClick={createPost}>创建帖子</按钮></main></div>)
}
​
导出默认主页

您的应用程序现已准备就绪!打开http://localhost:3000以查看它的实际效果:

您会注意到,每当您创建新帖子时,帖子列表都会自动更新。

由于 Convex 全局状态的端到端反应性,这种行为是可能的;每当数据更改时,使用查询的每个组件都会更新。

管理凸

运行npx convex dashboard以登录Convex 仪表板以管理您的应用程序数据、查看日志并查看函数执行和读/写的指标。

搜盘器App,全网主流网盘平台资源搜索,支持十大网盘搜索!

保护应用程序

保持应用程序数据的安全至关重要,Convex 使用身份提供者简化了数据保护。Convex 为 Auth0 提供了开箱即用的一流支持,您可以立即进行设置。

创建 Auth0 应用程序

登录到您的 Auth0 仪表板并创建一个新的单页 Web 应用程序。如果您还没有帐户,可以在 Auth0 上注册一个免费帐户。

从这个新应用程序的设置页面复制域和客户端 ID并保存以备后用。

在应用程序设置页面中,添加http://localhost:3000Allowed Callback URLs字段,如下所示。这将允许http://localhost:3000在开发期间使用 Auth0 登录。

设置 Auth0

首先运行npm i @auth0/auth0-react在您的项目中安装 Auth0。

然后,运行npx convex auth add以将 Auth0 作为身份提供者添加到 Convex。此命令将提示您输入之前复制的域和客户端 ID 。

components/在项目的根目录创建一个名为的新文件夹,并添加一个名为Login.tsxLogin 组件的新文件,该组件具有一个提示用户登录的按钮。

// 组件/Login.tsx
从“@auth0/auth0-react”导入 { useAuth0 }
​
导出函数登录(){const { isLoading, loginWithRedirect } = useAuth0()如果(正在加载){返回 <button className="btn btn-primary">加载中...</button>}返回 (<main className="py-4"><h1 className="text-center">凸聊天</h1><div className="text-center"><跨度><button className="btn btn-primary" onClick={loginWithRedirect}>登录</按钮></span></div></main>)
}

更新以pages/_app.tsx替换。ConvexProvider``ConvexProviderWithAuth0

导入'../styles/globals.css'
从 'convex/react-auth0' 导入 { ConvexProviderWithAuth0 }
从“凸/反应”导入 { ConvexReactClient }
从'../convex.json'导入conveconfig
从“下一个/应用程序”导入 { AppProps }
从'../components/Login'导入{登录}
​
常量凸 = 新的 ConvexReactClient(convexConfig.origin)
常量 authInfo = 凸配置.authInfo[0]
​
功能 MyApp({ 组件, pageProps }: AppProps) {返回 (<ConvexProviderWithAuth0客户={凸}authInfo={authInfo}已登录={<登录 />}><组件 {...pageProps} /></ConvexProviderWithAuth0>)
}
​
导出默认 MyApp

现在,当您打开应用程序时http://localhost:3000,您将看到一个登录按钮,而不是发布表单。

将 Auth0 与凸集成

现在您已经配置了 Auth0,您可以保护突变功能。该mutation函数提供认证信息作为auth对象。突变现在将addPost拒绝任何未经身份验证的请求。

// 凸/addPost.ts
从'./_generated/server'导入{突变}
​
导出默认突变(异步 ({分贝,身份验证},帖子:{作者:字符串;正文:字符串;标题:字符串}) => {常量身份 = 等待 auth.getUserIdentity()如果(!身份){throw new Error('调用 addPosts 时不存在身份验证!')}等待 db.insert('posts', post)}
)

您还可以更新前端的代码以使用登录用户的名称作为作者字段:

// pages/index.tsx
从“下一个”导入类型 { NextPage }
从“下一个/头”导入头
从 '../styles/Home.module.css' 导入样式
从“反应”导入 { useCallback, useState }
从“../convex/_generated/react”导入 {useMutation, useQuery};
从“@auth0/auth0-react”导入 {useAuth0};
​
常量主页:NextPage = () => {常量 {用户} = useAuth0()常量帖子 = useQuery('getPosts')const addPost = useMutation('addPost')
​const [title, setTitle] = useState('')const [body, setBody] = useState('')
​常量 createPost = async () => {如果(用户?。名称){等待 addPost({ body, author: user.name, title});}// 提交后重置输入集合体('')设置标题('')}
​返回 (<div className={styles.container}><头部><title>Next.js 凸面</title><meta name="description" content="由创建下一个应用生成" /><link rel="icon" href="/favicon.ico" /></头>
​<主类名={styles.main}><h1 className={styles.title}>欢迎使用{' '} 访问 <a href="https://nextjs.org">Next.js</a><a href="https://convex.dev">凸</a></h1>{帖子?(<><p className={styles.description}>{'帖子总数:'} {posts.length}</p>
​<ul>{posts.map((post) => (<li key={post._id.toString()}>{post.title}</li>))}</ul></>) : ('正在加载帖子...')}<输入类型={'文本'}价值={标题}占位符={'标题'}className={styles.inputStyles}onChange={(event) => setTitle(event.target.value)}/><文本区域价值={正文}行={5}placeholder={'帖子正文'}className={styles.inputStyles}onChange={(event) => setBody(event.target.value)}/><button className={styles.button} onClick={createPost}>创建帖子</按钮></main></div>)
}
​
导出默认主页

部署到 Vercel

要部署应用程序,请将您的代码(包括convex.json)推送到 GitHub 上的存储库并将其链接到您的Vercel 帐户:

将 build 命令替换为npx convex push && next build在部署时将最新功能推送到 Convex,并CONVEX_ADMIN_KEY从以下位置添加环境变量.env.local:

部署应用程序后,复制部署 URL ( .vercel.app):

将 URL 添加到Auth0 应用程序设置中的允许回调 URL列表中。http://localhost:3000

结论

您的应用程序现在部署在 Vercel 上。在本教程中,我们了解了全局状态管理以及如何使用 Convex 部署具有状态管理的 Next.js 应用程序。

我们还了解了如何使用 Auth0 保护应用程序并将其部署到 Vercel。您可以扩展上述应用程序以使用乐观更新和索引等高级功能,使其更快。

您可以立即免费试用 Convex,并在他们的文档中阅读有关使用它的更多信息。

LogRocket:全面了解生产 Next.js 应用程序

调试 Next 应用程序可能很困难,尤其是当用户遇到难以重现的问题时。如果您对监控和跟踪状态、自动显示 JavaScript 错误以及跟踪缓慢的网络请求和组件加载时间感兴趣,请尝试 LogRocket。

LogRocket就像一个用于网络和移动应用程序的 DVR,几乎可以记录下一个应用程序上发生的所有事情。无需猜测问题发生的原因,您可以汇总并报告问题发生时应用程序所处的状态。LogRocket 还监控您的应用程序的性能,并使用客户端 CPU 负载、客户端内存使用情况等指标进行报告。

LogRocket Redux 中间件包为您的用户会话增加了一层额外的可见性。LogRocket 记录来自 Redux 存储的所有操作和状态。

使用 Convex 进行状态管理的指南相关推荐

  1. Opengl编程指南第二章:状态管理、几何绘图

    //http://blog.csdn.net/longhuihu/article/details/7701874 1.绘图基础 清除窗口 glClearColor(0.0, 0.0, 0.0, 0.0 ...

  2. Flutter 状态管理指南之 Provider

    2019 Google I/O 大会,Flutter 团队在"Pragmatic State Management in Flutter "演讲上正式介绍了 Provider.自此 ...

  3. 选择正确的 React 状态管理解决方案的指南

    编者注 :本文于 2022 年 9 月 23 日更新,添加了关于为什么我们需要在 React 中进行状态管理的信息,添加了之前未包含在文章中的其他状态管理工具,例如 Jotai.MobX 和 Zusa ...

  4. 操作系统CnetOS_7—systemd管理实践指南

    systemd管理实践指南 管理systemd CentOS 7 使用systemd替换了SysV.Systemd目的是要取代Unix时代以来一直在使用的init系统,兼容SysV和LSB的启动脚本, ...

  5. React组件设计实践总结05 - 状态管理

    今天是 520,这是本系列最后一篇文章,主要涵盖 React 状态管理的相关方案. 前几篇文章在掘金首发基本石沉大海, 没什么阅读量. 可能是文章篇幅太长了?掘金值太低了? 还是错别字太多了? 后面静 ...

  6. 通过Dapr实现一个简单的基于.net的微服务电商系统(五)——一步一步教你如何撸Dapr之状态管理...

    状态管理和上一章的订阅发布都算是Dapr相较于其他服务网格框架来讲提供的比较特异性的内容,今天我们来讲讲状态管理. 目录: 一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr ...

  7. 程序员学习指南_程序员管理压力指南

    程序员学习指南 by Daragh Byrne 达拉·伯恩(Daragh Byrne) 程序员管理压力指南 (A programmer's guide to managing stress) 我几乎一 ...

  8. 一文带你全面体验八种状态管理库

    动手点关注 干货不迷路 写在前面 状态管理库伴随着数据驱动类框架诞生以来,一直都是个带争议的话题,社区里关于这个方向的讨论文章也是数不胜数,本文写作的目的并不是去详细解答每一款状态库的设计原理和最佳实 ...

  9. 第 8 章 管线以及管线状态管理

    首发于 Vulkan 学习指南 关注专栏 写文章 第 8 章 管线以及管线状态管理 SnowFox 图形学 AI 分布式 操作系统 编译器 架构 后端 多线程 9 人 赞同了该文章 第 8 章 管线以 ...

  10. 轻量级的状态管理解决方案-zustand

    状态管理在现在的前端项目成为了必不可少的环节,三大框架也相继推出了自己的状态管理工具.当然也有一些非常优秀的第三方状态管理工具,比如:flux.mobx.dva.zustand等,今天我们就来了解下这 ...

最新文章

  1. java内存模型-JMM
  2. 网络慢是带宽不足?优化网络带宽的5个小窍门
  3. mybatis 创建session, 缓存, 执行SQL
  4. ubuntu编译android4.0
  5. 各大浏览器CSS Hack收集
  6. python except用法和作用_python上手--异常处理与文件
  7. centos7 安装 mysql8 强制修改密码
  8. Android指纹识别
  9. PMP干货教你一秒选对PMP考试答案!
  10. arcmap操作Excel文件没有注册类解决办法
  11. javascript 替换
  12. 线性系统理论2 系统状态和状态空间
  13. Google地图坐标拾取器,地图选点,获取经纬度
  14. vue构建项目对接口的调用封装
  15. VisualAssistX无法加载,加载问题异常解决
  16. 大数据同步利器: 表格存储全增量一体消费通道
  17. 华为究竟做了多少芯片?
  18. Sailfish 浏览器是基于 Gecko 引擎开发
  19. https生成根证书、服务证书
  20. 如何压缩文件到最小?

热门文章

  1. Android 网络请求框架浅解析
  2. 服务器连接无线键盘,【罗技 K375s 无线蓝牙键盘使用总结】连接|手感_摘要频道_什么值得买...
  3. 比较好的运动耳机,好用的运动耳机推荐
  4. 一元三次方程求根公式及韦达定理
  5. fastlane php,fastlane安装与初体验
  6. Vue 爬坑之旅 -- 用自定义指令解决 IOS 12 中键盘收起后页面底部有留白的问题
  7. 中标麒麟linux操作系统下Chrome/Chromium的安装
  8. Android踩坑记录:This view is not constrained vertically
  9. Python实现qq自动发送消息
  10. halcon测试篇:求两条线之间的交点