Next.js中如何将客户端组件状态传递给服务端组件?
问题:Next.js中客户端组件向服务端组件传递表单数据以修改XML文件
我用TypeScript和Next.js读写本地存储的包含<user>标签的.xml文件,现有三个核心组件:
- UserTable组件:展示.xml中的
<user>信息,负责数据展示 - AddUserForm组件:客户端组件,负责输入新用户数据,数据存在
formValues的useState变量中 - AddNewUser组件:默认服务端组件,目前用模拟数据操作.xml文件
我需要把AddUserForm里的formValues传给AddNewUser组件,用输入的数据替换模拟数据来添加新<user>标签。试过useRouter和SSR等方法,都因为实现复杂没成功。
现有组件代码
AddUserForm组件(客户端组件)
'use client' import Link from "next/link"; import { useState } from 'react'; const AddUserForm = () => { const [formValues, setFormValues] = useState({ name: '', phone: '', }); const handleChange = (e: any) => { const { id, value } = e.target; setFormValues((prevValues) => ({ ...prevValues, [id]: value, })); }; const handleSubmit = (e: any) => { e.preventDefault(); }; return ( <div> <form onSubmit={handleSubmit}> <div> <label> Name </label> <input id="name" type="text" placeholder="Name" value={formValues.name} onChange={handleChange} /> </div> <div> <label> Phone </label> <input id="phone" type="text" placeholder="Phone" value={formValues.phone} onChange={handleChange} /> </div> <div> <Link href="/"> <button> Go Back </button> </Link> <button type="submit"> Add </button> </div> </form> </div> ); }; export default AddUserForm;
AddNewUser组件(服务端组件)
import fs from 'fs'; import { parseString, Builder } from 'xml2js'; const AddNewUser = (props: any) => { const xmlFilePath = './public/user.xml'; const xmlContent = fs.readFileSync(xmlFilePath, 'utf-8'); parseString(xmlContent, { explicitArray: false }, (error: any, result: any) => { if (error) { console.error('Error parsing user.xml:', error); } else { const newUser = { $: { name: 'New User', phone: '123456789' }, }; result.root.users.user.push(newUser); // Converting updated XML object to XML string const builder = new Builder(); const updatedXmlContent = builder.buildObject(result); // Updating the new XML content back to the file fs.writeFileSync(xmlFilePath, updatedXmlContent); } }); return ( <div> </div> ) } export default AddNewUser
解决方案:用Next.js API Route中转数据
客户端组件无法直接调用服务端组件的文件操作逻辑,API路由是最直接的解决方案:
步骤1:创建API路由处理XML写入
在app/api/add-user/route.ts创建API路由,把AddNewUser的文件操作逻辑迁移过来:
import fs from 'fs'; import { parseString, Builder } from 'xml2js'; import { NextResponse } from 'next/server'; export async function POST(request: Request) { try { const { name, phone } = await request.json(); const xmlFilePath = './public/user.xml'; const xmlContent = fs.readFileSync(xmlFilePath, 'utf-8'); return new Promise((resolve, reject) => { parseString(xmlContent, { explicitArray: false }, (error, result) => { if (error) { console.error('解析XML出错:', error); return reject(NextResponse.json({ success: false, error: '解析XML失败' }, { status: 500 })); } // 兼容单个用户的情况,确保user是数组 if (!Array.isArray(result.root.users.user)) { result.root.users.user = [result.root.users.user]; } const newUser = { $: { name, phone } }; result.root.users.user.push(newUser); const builder = new Builder(); const updatedXmlContent = builder.buildObject(result); fs.writeFileSync(xmlFilePath, updatedXmlContent); resolve(NextResponse.json({ success: true }, { status: 200 })); }); }); } catch (error) { return NextResponse.json({ success: false, error: '服务器错误' }, { status: 500 }); } }
步骤2:修改AddUserForm组件提交逻辑
更新客户端组件的handleSubmit函数,通过POST请求把表单数据传给API路由:
'use client' import Link from "next/link"; import { useState } from 'react'; const AddUserForm = () => { const [formValues, setFormValues] = useState({ name: '', phone: '', }); const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { id, value } = e.target; setFormValues((prevValues) => ({ ...prevValues, [id]: value, })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { const response = await fetch('/api/add-user', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formValues), }); if (response.ok) { setFormValues({ name: '', phone: '' }); alert('用户添加成功'); // 可在此处跳转到用户列表页 } else { alert('添加失败,请重试'); } } catch (error) { console.error('提交出错:', error); alert('网络错误,请重试'); } }; return ( <div> <form onSubmit={handleSubmit}> <div> <label> 姓名 </label> <input id="name" type="text" placeholder="姓名" value={formValues.name} onChange={handleChange} required /> </div> <div> <label> 电话 </label> <input id="phone" type="text" placeholder="电话" value={formValues.phone} onChange={handleChange} required /> </div> <div> <Link href="/"> <button type="button"> 返回 </button> </Link> <button type="submit"> 添加 </button> </div> </form> </div> ); }; export default AddUserForm;
步骤3:移除AddNewUser组件
现在文件操作逻辑已移到API路由,AddNewUser组件不再需要,可直接删除。
内容的提问来源于stack exchange,提问作者Ishaan_B
相关产品推荐
相关产品推荐

