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 排版

相关推荐
uzong4 小时前
后端线上发布计划模板
后端
uzong5 小时前
软件工程师应该关注的几种 UML 图
后端
上进小菜猪6 小时前
基于 YOLOv8 的 100 类中药材智能识别实战 [目标检测完整源码]
后端
码事漫谈8 小时前
AI 技能工程入门:从独立能力到协作生态
后端
码事漫谈8 小时前
构建高并发AI服务网关:C++与gRPC的工程实践
后端
颜酱9 小时前
前端必备动态规划的10道经典题目
前端·后端·算法
半夏知半秋10 小时前
rust学习-闭包
开发语言·笔记·后端·学习·rust
LucianaiB10 小时前
【保姆级教程】10分钟把手机变成AI Agent:自动刷课、回消息,学不会我“退网”!
后端
Mr -老鬼11 小时前
功能需求对前后端技术选型的横向建议
开发语言·前端·后端·前端框架
IT=>小脑虎11 小时前
Go语言零基础小白学习知识点【基础版详解】
开发语言·后端·学习·golang