Next.js13实战开发,在服务端组件中使用Forms表单超方便的前后交互

如果想看专栏的方式可以点击进入Next图册目实践

通过之前的分享,我们已经知道Form表单提交可以在app/api/route.ts使用handle的方式进行处理。

但其实Next.js13 App Router中提供了一种使用服务器操作处理表单提交和数据更改的强大方法。

服务器操作的工作原理

使用服务器操作,无需手动创建 API 终结点。相反,您可以定义可以直接从组件调用的异步服务器函数。

服务器操作可以在服务器组件中定义,也可以从客户端组件调用。在服务器组件中定义操作允许表单在没有 JavaScript 的情况下运行,从而提供渐进式增强。

简单点来说你可以在use client中直接调用服务端的方法,它可以区分你是服务端方法还是客户端方法!是不突然就感觉很逆天了?

要使用这个特性我们首先需要在next.config.js文件中启动服务器的操作

java 复制代码
module.exports = {
  experimental: {
    serverActions: true,
  },
}

要点需知:

  • 从服务端组件调用服务器操作的表单可以在没有 JavaScript (浏览器客户端) 的情况下运行。
  • 如果 JavaScript 尚未加载,则从客户端组件调用服务器操作的表单将对提交进行排队,从而优先考虑客户端冻结。(客户出现UI线程阻塞)
  • 服务器操作继承它们所用页面或布局的运行时。
  • 现在的版本如果路由使用serverActions,必须要动态呈现。

serverActions在操作的过程中,是不会整个页面提交的。Next.js内部回知道你想返回什么内容。具体内容可以细看Form中的错误例子。

如何使用?

serverActions,请在服务端组件中定义serverActions。操作可以与函数内第一行定义,也可以在文件顶部具有 use server 指令的单独文件中定义。

javascript 复制代码
export default function Page() {
  async function create(formData: FormData) {
    'use server'
 
    // mutate data
    // revalidate cache
  }
  // 这里的action不在写 url地址 可以直接填写方法
  return <form action={create}>...</form> 
}

当然你也可以写出这种方式

javascript 复制代码
// app/actions.ts
 'use server'
export default async function create(formData: FormData) {
    // mutate data
    // revalidate cache
}

// app/page.tsx
import create from '@/app/actions'
export default function Page() {
  // 这里的action不在写 url地址 可以直接填写方法
  return <form action={create}>...</form> 
}

表单校验

对于一个web应用开发来说,From组件的数据校验是必不可少的。我们建议使用 HTML 验证,就像 required 和 进行 type="email" 基本表单验证一样。

对于更高级的服务器端验证,梦兽编程这里使用zod进行表单的校验,相比于route.ts的handle 可以少写一步代码。

ini 复制代码
req.fromData().then(values=>{})
javascript 复制代码
import { z } from 'zod'
 
const schema = z.object({
  // ...
})
 
export default async function submit(formData: FormData) {
  const parsed = schema.parse({
    id: formData.get('id'),
  })
  // ...
}

提交的状态怎么做呢?

这里需要用到react-dom的一些api,

javascript 复制代码
'use client'
 
import { experimental_useFormStatus as useFormStatus } from 'react-dom'
 
function SubmitButton() {
  const { pending } = useFormStatus()
 
  return (
    <button disabled={pending}>{pending ? 'Submitting...' : 'Submit'}</button>
  )
}

From的错误状态处理

javascript 复制代码
'use server'
 
export async function create(formData: FormData) {
  try {
    await createItem(formData.get('item'))
    revalidatePath('/')
    return { message: 'Success!' }
  } catch (e) {
    return { message: 'There was an error.' }
  }
}

我们依然可以返回json格式,回顾上面所说,我们在客户端组件中就可以直接获取操作,前方高能的前后端RPC通信

javascript 复制代码
'use client'
 
import { create } from './actions'
import { useState } from 'react'
 
export default function Page() {
  const [message, setMessage] = useState<string>('')
 
  async function onCreate(formData: FormData) {
    const res = await create(formData)
    //是不是很方便呢?这不比TRPC方便?
    setMessage(res.message)
  }
 
  return (
    <form action={onCreate}>
      <input type="text" name="item" />
      <button type="submit">Add</button>
      <p>{message}</p>
    </form>
  )
}

其他

其他关于 headers cookie 等操作和Node.js,Next.js中route的handle操作类似。也是web常用技巧,这里就不展开说了,感兴趣的可以回去观看之前的内容。

感谢你的阅读,期待在下一篇文章中再次见到你!

我的B站视频号更多视频动态。

本文使用 markdown.com.cn 排版

相关推荐
冬奇Lab3 分钟前
一天一个开源项目(第54篇):Supabase - 开源的 Postgres 开发平台,Firebase 替代方案
后端·开源·资讯
中年程序员一枚1 小时前
spring-cloud-starter-openfeign现实中的运行逻辑
java·spring boot·后端
why技术1 小时前
我拿到了腾讯QClaw的内测码,然后沉默了。
前端·后端
只能是遇见2 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端
wefly20172 小时前
无需安装、开箱即用!m3u8live.cn 在线 HLS 播放器,调试直播流效率翻倍
前端·后端·python·前端开发工具·后端开发工具
IT_陈寒3 小时前
React组件性能翻倍的5个冷门技巧,90%的开发者不知道!
前端·人工智能·后端
aq55356003 小时前
SpringBoot有几种获取Request对象的方法
java·spring boot·后端
dotNET实验室3 小时前
ASP.NET Core 外部依赖调用治理实战:HttpClientFactory、Polly 与幂等边界
后端
Nturmoils3 小时前
从「亡羊补牢」到「规则先行」:金仓数据库 SQL 防火墙实战解析
数据库·后端
Oneslide4 小时前
Harbor 启动失败故障排查与解决:从“Cannot allocate memory”到“Operation not permitted”
后端