Next.js 和 GraphQL:全栈开发的完美结合

Q神日志 2023-07-02 16:45:23

你将学到什么

在今天的文章中,我们将使用 Next.js 和 GraphQL Yoga 创建一个完整的堆栈应用程序。

 

动图最后结果

 

本文涵盖什么内容

  • Next.js 应用程序路由器和操作
  • GraphQL Yoga 集成
  • 对数据库执行Get、Create、Delete等操作

先决条件

在开始本文之前,建议您了解 React、Next.js 和 GraphQL。

创建项目

要在 Remix 中初始化项目,我们执行以下命令:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>npx create-next-app@latest my-app
</code></span></span>

 

使用的设置包括 TypeScript、ESLint、Tailwind CSS,我们正在使用app路由器。

我们使用以下命令启动开发服务器:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>npm run dev
</code></span></span>

 

除了基本配置之外,我们还使用daisyUI库来使用预先样式化的组件。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>npm <span style="color:var(--syntax-text-color)">install </span>daisyui
</code></span></span>

 

然后我们将库添加到文件中的插件列表中tailwind.config.js,我们还可以在其中定义要使用的主题,如下所示:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-name-color)">module</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">exports</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>
  <span style="color:var(--syntax-name-color)">plugins</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">require</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">daisyui</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">)],</span>
  <span style="color:var(--syntax-name-color)">daisyui</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">themes</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">winter</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">],</span>
  <span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

 

应用程序设置准备就绪后,我们可以继续下一步。

后端设置

首先,我们需要配置与数据库的连接,以便我们可以将数据保存在应用程序中。为了促进整个过程,我们将使用 ORM,在本文中我决定选择Drizzle ORM。对于数据库,我决定使用 SQLite,因为它是最容易访问的。

我们首先安装依赖项:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>npm <span style="color:var(--syntax-text-color)">install </span>drizzle-orm better-sqlite3
npm <span style="color:var(--syntax-text-color)">install</span> <span style="color:var(--syntax-error-color)">-D</span> drizzle-kit @types/better-sqlite3
</code></span></span>

 

然后在该server/文件夹中,我们将创建一个名为 的文件夹db/,其中将包含连接和数据库架构。

从配置开始,让我们server/db/config.ts使用以下内容创建文件:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">drizzle</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">drizzle-orm/better-sqlite3</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">migrate</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">drizzle-orm/better-sqlite3/migrator</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">Database</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">better-sqlite3</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">sqlite</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-name-color)">Database</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">sqlite.db</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">);</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">db</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">drizzle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">sqlite</span><span style="color:var(--syntax-text-color)">);</span>

<span style="color:var(--syntax-name-color)">migrate</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">db</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">migrationsFolder</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./server/db/migrations</span><span style="color:var(--syntax-string-color)">"</span> <span style="color:var(--syntax-text-color)">});</span>
</code></span></span>

 

下一步是创建数据库模式,在今天的文章中,我们将在数据库中只有一个表,并使用todos三列进行调用,如下所示:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">sqliteTable</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">text</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">integer</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">drizzle-orm/sqlite-core</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">todos</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">sqliteTable</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">todos</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">integer</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">id</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">primaryKey</span><span style="color:var(--syntax-text-color)">(),</span>
  <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">text</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">username</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">notNull</span><span style="color:var(--syntax-text-color)">(),</span>
  <span style="color:var(--syntax-name-color)">createdAt</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">integer</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">createdAt</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">notNull</span><span style="color:var(--syntax-text-color)">(),</span>
<span style="color:var(--syntax-text-color)">});</span>
</code></span></span>

 

上面的代码位于server/db/schema.ts文件中,在创建数据库迁移和作为实体时将考虑该文件。现在让package.json我们添加以下脚本:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>
  <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">scripts</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-comment-color)">// ...</span>
    <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">db:migrations</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">drizzle-kit generate:sqlite --out ./server/db/migrations --schema ./server/db/schema.ts</span><span style="color:var(--syntax-string-color)">"</span>
  <span style="color:var(--syntax-text-color)">},</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

从上面的脚本中,我们可以运行以下命令来创建迁移,同时考虑到创建的架构:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>npm run db:migrations
</code></span></span>

 

一旦完成,预计migrations/将在文件夹内创建该文件夹server/db/

一旦我们准备好数据层,我们就可以开始处理 GraphQL 层,首先安装这些依赖项:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)"># graphql related dependencies</span>
npm <span style="color:var(--syntax-text-color)">install </span>garph graphql-yoga graphql
<span style="color:var(--syntax-comment-color)"># JS Dates</span>
npm <span style="color:var(--syntax-text-color)">install </span>dayjs
</code></span></span>

 

下一步无疑是使用Garph创建 GraphQL 架构,以创建完全类型安全的 API,而无需进行代码生成。

我们的应用程序的架构将只有一个查询,它将负责返回todos数据库中的所有内容。我们还将有两个 Mutations,一个用于插入 a,todo另一个用于删除现有的todo

为此,我们创建一个名为gql/in 的server/文件夹,其中包含与我们的架构相关的所有内容,可能类似于以下内容:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">GarphSchema</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">garph</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">g</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-name-color)">GarphSchema</span><span style="color:var(--syntax-text-color)">();</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">TodoGQL</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">type</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Todo</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">int</span><span style="color:var(--syntax-text-color)">(),</span>
  <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
  <span style="color:var(--syntax-name-color)">createdAt</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">int</span><span style="color:var(--syntax-text-color)">(),</span>
<span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">queryType</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">type</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Query</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">getTodos</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">ref</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">TodoGQL</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">list</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">description</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Gets an array of todos</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">),</span>
<span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">mutationType</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">type</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Mutation</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">addTodo</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span>
    <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">ref</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">TodoGQL</span><span style="color:var(--syntax-text-color)">)</span>
    <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">args</span><span style="color:var(--syntax-text-color)">({</span>
      <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-text-color)">})</span>
    <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">description</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Adds a new todo</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">),</span>
  <span style="color:var(--syntax-name-color)">removeTodo</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span>
    <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">ref</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">TodoGQL</span><span style="color:var(--syntax-text-color)">)</span>
    <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">optional</span><span style="color:var(--syntax-text-color)">()</span>
    <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">args</span><span style="color:var(--syntax-text-color)">({</span>
      <span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">int</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-text-color)">})</span>
    <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">description</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Removes an existing todo</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">),</span>
<span style="color:var(--syntax-text-color)">});</span>
</code></span></span>

 

使用文件中创建的架构schema.ts,我们现在可以创建resolvers.ts包含查询逻辑和 API 的每个突变的架构。可能如下所示:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">InferResolvers</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">garph</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">YogaInitialContext</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">graphql-yoga</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">eq</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">drizzle-orm</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">dayjs</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">dayjs</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">mutationType</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">queryType</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./schema</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">db</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../db/config</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">todos</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../db/schema</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Resolvers</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">InferResolvers</span><span style="color:var(--syntax-error-color)"><</span>
  <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">Query</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">typeof</span> <span style="color:var(--syntax-name-color)">queryType</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">Mutation</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">typeof</span> <span style="color:var(--syntax-name-color)">mutationType</span> <span style="color:var(--syntax-text-color)">},</span>
  <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">context</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">YogaInitialContext</span> <span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">resolvers</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Resolvers</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">Query</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">getTodos</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">_</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">__</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">ctx</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">db</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">select</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-declaration-color)">from</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">todos</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">all</span><span style="color:var(--syntax-text-color)">();</span>
    <span style="color:var(--syntax-text-color)">},</span>
  <span style="color:var(--syntax-text-color)">},</span>
  <span style="color:var(--syntax-name-color)">Mutation</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">addTodo</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">_</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">title</span> <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-name-color)">ctx</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">db</span>
        <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">insert</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">todos</span><span style="color:var(--syntax-text-color)">)</span>
        <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">values</span><span style="color:var(--syntax-text-color)">({</span>
          <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">,</span>
          <span style="color:var(--syntax-name-color)">createdAt</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">dayjs</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">unix</span><span style="color:var(--syntax-text-color)">(),</span>
        <span style="color:var(--syntax-text-color)">})</span>
        <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">returning</span><span style="color:var(--syntax-text-color)">()</span>
        <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">get</span><span style="color:var(--syntax-text-color)">();</span>
    <span style="color:var(--syntax-text-color)">},</span>
    <span style="color:var(--syntax-name-color)">removeTodo</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">_</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">id</span> <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-name-color)">ctx</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">db</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">delete</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">todos</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">where</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">eq</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">todos</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">)).</span><span style="color:var(--syntax-name-color)">returning</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-declaration-color)">get</span><span style="color:var(--syntax-text-color)">();</span>
    <span style="color:var(--syntax-text-color)">},</span>
  <span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

 

创建模式和解析器后,我们现在需要创建index.ts用于构建 GraphQL 模式的文件,以便 GraphQL Yoga 可以使用它。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">buildSchema</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">garph</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">resolvers</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./resolvers</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">g</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./schema</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">schema</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">buildSchema</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">g</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">resolvers</span> <span style="color:var(--syntax-text-color)">});</span>
</code></span></span>

 

这样我们就准备好了一切,现在可以跳转到我们将使用包含以下内容的文件router app创建以下文件夹结构的位置:app/api/graphql/route.ts

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">createYoga</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">graphql-yoga</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">schema</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../../../server/gql</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">handleRequest</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">createYoga</span><span style="color:var(--syntax-text-color)">({</span>
  <span style="color:var(--syntax-name-color)">schema</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">graphqlEndpoint</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">/api/graphql</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">fetchAPI</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">Request</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">Response</span> <span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">handleRequest</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-name-color)">GET</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">handleRequest</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-name-color)">POST</span> <span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

在上面的代码块中,我们创建了一个自定义路由处理程序,它将创建一个GraphQL Yoga实例,该实例将提供我们的 API,同时考虑到刚才创建的架构和解析器。

后端完成后,我们可以继续下一点。

可重复使用的组件

在开始处理页面之前,让我们先处理页面中将使用的一些组件。这些组件与列表和将在其中呈现的元素(行)以及一些操作相关。

首先安装以下依赖项:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>npm <span style="color:var(--syntax-text-color)">install </span>graphql-request zod
</code></span></span>

 

接下来,让我们创建一个<ListItem />组件,该组件将与列表中的每一行相对应,该列表将在应用程序的根目录中呈现。该组件将接收一些 props,例如todoIdtitle和一个removeItem()函数。为了具有交互性,该组件将在客户端呈现。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">use client</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">LiHTMLAttributes</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">react</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">interface</span> <span style="color:var(--syntax-name-color)">Props</span> <span style="color:var(--syntax-declaration-color)">extends</span> <span style="color:var(--syntax-name-color)">LiHTMLAttributes</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">HTMLLIElement</span><span style="color:var(--syntax-error-color)">></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">todoId</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-text-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-text-color)">removeItem</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-declaration-color)">void</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">default</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">ListItem</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">todoId</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">removeItem</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">...</span><span style="color:var(--syntax-name-color)">rest</span> <span style="color:var(--syntax-text-color)">}:</span> <span style="color:var(--syntax-name-color)">Props</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span>
      <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"card w-96 bg-base-100 shadow-xl cursor-pointer"</span>
      <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">...</span><span style="color:var(--syntax-name-color)">rest</span><span style="color:var(--syntax-string-color)">}</span>
      <span style="color:var(--syntax-name-color)">onClick</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">removeItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">todoId</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">div</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"card-body"</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">p</span><span style="color:var(--syntax-text-color)">></span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">p</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

然后我们可以创建一些将在应用程序列表中使用的操作,我们只需确保这些函数在调用时始终在服务器端运行。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">use server</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">revalidatePath</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">next/cache</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">GraphQLClient</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">gql</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">graphql-request</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">mutation</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">gql</span><span style="color:var(--syntax-string-color)">`
  mutation removeTodo($id: Int!) {
    removeTodo(id: $id) {
      id
    }
  }
`</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">removeTodo</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">graphQLClient</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-name-color)">GraphQLClient</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">http://localhost:3000/api/graphql</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">graphQLClient</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">request</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">mutation</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">id</span> <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-name-color)">revalidatePath</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

上面的代码是在app/components/文件夹内创建的,更具体地说,list/是在包含文件中的函数的文件夹中创建actions.ts的,并且文件中将包含组件代码index.tsx。该组件仍然需要创建并将在服务器端渲染。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">Infer</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">garph</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">request</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">gql</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">graphql-request</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">TodoGQL</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../../server/gql/schema</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">ListItem</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../ListItem</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">removeTodo</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./actions</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">query</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">gql</span><span style="color:var(--syntax-string-color)">`
  query getTodos {
    getTodos {
      id
      title
    }
  }
`</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">interface</span> <span style="color:var(--syntax-name-color)">QueryData</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-text-color)">getTodos</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">Array</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">Infer</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">typeof</span> <span style="color:var(--syntax-name-color)">TodoGQL</span><span style="color:var(--syntax-error-color)">>></span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">default</span> <span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">List</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">getTodos</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">request</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-name-color)">QueryData</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">http://localhost:3000/api/graphql</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
    <span style="color:var(--syntax-name-color)">query</span>
  <span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">ul</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"space-y-4"</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">getTodos</span><span style="color:var(--syntax-text-color)">?.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">todo</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
        <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">ListItem</span>
            <span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">todo</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">todo</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-name-color)">todoId</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">todo</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-name-color)">removeItem</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">removeTodo</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-text-color)">/></span>
        <span style="color:var(--syntax-text-color)">);</span>
      <span style="color:var(--syntax-text-color)">})</span><span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

创建可重用组件后,我们现在可以继续下一步。

路线设置

现在我们已经准备好了需要使用的一切,我们可以开始定义应用程序的路由。我们将在应用程序中使用的路由如下:

  • app/page.tsx- 应用程序的主路径,我们将在其中列出所有这些内容,并且可以与它们交互以删除它们
  • app/new/page.tsx- 表单出现的位置以及验证提交的数据并进行相应修改的操作

现在考虑到这一点,我们可以转到该layout.tsx文件并进行以下更改:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./globals.css</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">metadata</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Today's tasks</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">default</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">RootLayout</span><span style="color:var(--syntax-text-color)">({</span>
  <span style="color:var(--syntax-name-color)">children</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-text-color)">}:</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-text-color)">children</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">React</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">ReactNode</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">html</span> <span style="color:var(--syntax-name-color)">lang</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"en"</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">body</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"h-screen w-screen bg-neutral"</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">section</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"container mx-auto p-4"</span><span style="color:var(--syntax-text-color)">></span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">children</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">section</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">body</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">html</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

接下来,在page.tsx文件中,我们将添加一个Suspense边界,以便我们可以利用 html 流,当列表解析异步请求并呈现 html 时,我们将显示一个后备。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">React</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">Suspense</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">react</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">Link</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">next/link</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">dayjs</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">dayjs</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">List</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../components/List</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">default</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">Page</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">div</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"space-y-6"</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">div</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"flex flex-row items-start justify-between max-w-xl"</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">span</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"space-y-2"</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">h1</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text-3xl text-primary-content"</span><span style="color:var(--syntax-text-color)">></span>Today<span style="color:var(--syntax-text-color)">&apos;</span>s tasks<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">h1</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">p</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text-lg"</span><span style="color:var(--syntax-text-color)">></span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">dayjs</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">format</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">dddd, D MMM</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">p</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">span</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">Link</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"btn"</span> <span style="color:var(--syntax-name-color)">href</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"/new"</span><span style="color:var(--syntax-text-color)">></span>
          New Task
        <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-name-color)">Link</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>

      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">Suspense</span> <span style="color:var(--syntax-name-color)">fallback</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">span</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"loading loading-ring loading-lg"</span> <span style="color:var(--syntax-text-color)">/></span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">List</span> <span style="color:var(--syntax-text-color)">/></span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-name-color)">Suspense</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

最后但并非最不重要的一点是,仍然需要创建负责在文件的文件夹todo内插入新内容的页面。在此组件中,我们将创建一个模式zod来验证表单数据,在该页面内,我们将有一个名为 的函数,该函数应仅在服务器端运行。app/new/page.tsxaddTodo()

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">Link</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">next/link</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">redirect</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">next/navigation</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">GraphQLClient</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">gql</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">graphql-request</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">z</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">zod</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">mutation</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">gql</span><span style="color:var(--syntax-string-color)">`
  mutation addTodo($title: String!) {
    addTodo(title: $title) {
      id
    }
  }
`</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">formValuesSchema</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">object</span><span style="color:var(--syntax-text-color)">({</span>
  <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">min</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-literal-color)">3</span><span style="color:var(--syntax-text-color)">),</span>
<span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">addTodo</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">formData</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">FormData</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">use server</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">formValues</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{}</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-declaration-color)">any</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-declaration-color)">for</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-declaration-color)">of</span> <span style="color:var(--syntax-text-color)">[...</span><span style="color:var(--syntax-name-color)">formData</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">entries</span><span style="color:var(--syntax-text-color)">()])</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">includes</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">ACTION_ID</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">))</span> <span style="color:var(--syntax-declaration-color)">continue</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-name-color)">formValues</span><span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">valueOf</span><span style="color:var(--syntax-text-color)">();</span>
  <span style="color:var(--syntax-text-color)">}</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">parsed</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">formValuesSchema</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">parseAsync</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">formValues</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">graphQLClient</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-name-color)">GraphQLClient</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">http://localhost:3000/api/graphql</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">graphQLClient</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">request</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">mutation</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">parsed</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-name-color)">redirect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">default</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">Page</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">div</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"max-w-xs space-y-6"</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">Link</span> <span style="color:var(--syntax-name-color)">href</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">".."</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"btn btn-ghost"</span><span style="color:var(--syntax-text-color)">></span>
        Go back
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-name-color)">Link</span><span style="color:var(--syntax-text-color)">></span>

      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">form</span> <span style="color:var(--syntax-name-color)">action</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">addTodo</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"space-y-4"</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">label</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"label"</span><span style="color:var(--syntax-text-color)">></span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">span</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"label-text"</span><span style="color:var(--syntax-text-color)">></span>Task title<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">span</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span>
            <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text"</span>
            <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"title"</span>
            <span style="color:var(--syntax-name-color)">placeholder</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"Type here..."</span>
            <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"input input-bordered w-full max-w-xs"</span>
            <span style="color:var(--syntax-name-color)">required</span>
            <span style="color:var(--syntax-name-color)">minLength</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-literal-color)">3</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-text-color)">/></span>
        <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>

        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">button</span> <span style="color:var(--syntax-name-color)">className</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"btn btn-block"</span> <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"submit"</span><span style="color:var(--syntax-text-color)">></span>
          Submit
        <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">button</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">form</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>

 

至此,我结束了本文的最后一步。

结论

我希望您觉得这篇文章很有帮助,无论您是在现有项目中使用这些信息还是只是为了好玩而尝试一下。

 

...全文
3796 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

6

社区成员

发帖
与我相关
我的任务
社区描述
分享
java-rocketmqpygame前端 个人社区 广东省·广州市
社区管理员
  • Q shen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧