使用 Convex 进行状态管理的指南

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

大家好,我是讯享网,很高兴认识大家。

像 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 存储的所有操作和状态。

小讯
上一篇 2025-02-14 22:15
下一篇 2025-02-06 21:29

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/130108.html