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

相关推荐
2401_857622661 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589361 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没2 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码4 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries5 小时前
读《show your work》的一点感悟
后端
A尘埃5 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23075 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code5 小时前
(Django)初步使用
后端·python·django
代码之光_19805 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端