Next.js中设置默认属性数据及解决更新表单字段丢失问题
问题:Next.js更新表单未修改字段提交后被清空
我正在开发一个具备CRUD功能的React/Next.js应用,更新表单在提交时出现异常:
- 不修改任何字段提交,title和content字段的数据会无故消失
- 仅修改title字段提交,content字段会被清空
示例
修改前:
- title: aaa
- content: bbb
仅将title修改为aaaa后提交,结果:
- title: aaaa
- content: (空值)
原代码如下:
import Link from "next/link"; import { client } from "@/libs/client"; import { useRouter } from "next/router"; import React, { useState } from "react"; export default function Update ({ blog }) { const router = useRouter() const id = blog.id; const [title, setTitle] = useState(""); const [content, setContent] = useState(""); async function update(event) { event.preventDefault() client.update({ endpoint: "blogs", content: { title: title, content: content, }, contentId: id }).then((res) => { if (res.status === 401) { alert("Something wrong is happening") } else { alert("Editing is done") router.push(`/`) } }) } return ( <> <div className='main'> <h1 className=''>Edit page</h1> <div className="contents"> <div> <form onSubmit={ update }> <div> <h2>Here's title</h2> <input name="title" type="text" defaultValue={blog.title} onChange={(event) => setTitle(event.target.value)} /> </div> <div> <h2>Contents</h2> <textarea name="content" defaultValue={blog.content} onChange={(event) => setContent(event.target.value)} ></textarea> </div> <button type="submit"> <p>Submit</p> </button> </form> </div> </div> </div> </> ); } export const getStaticPaths = async () => { const data = await client.get({ endpoint: "blogs" }); const paths = data.contents.map((content) => `/blog/${content.id}/update`); return { paths, fallback: false }; }; export const getStaticProps = async (context) => { const id = context.params.id; const data = await client.get({ endpoint: "blogs", contentId: id }); return { props: { blog: data, }, }; };
问题原因
- 状态初始化错误:
useState的初始值设为空字符串,而非传入的blog数据,导致未修改字段在提交时使用空值 - 表单绑定方式错误:使用
defaultValue仅在初始渲染时赋值,未和状态双向绑定,表单显示的原始数据未同步到状态中
修复方案
1. 用blog数据初始化状态
将useState的初始值替换为blog中的对应字段:
const [title, setTitle] = useState(blog.title); const [content, setContent] = useState(blog.content);
2. 用value绑定表单控件
把defaultValue改为value,确保表单控件的值始终和状态同步:
<input name="title" type="text" value={title} onChange={(event) => setTitle(event.target.value)} /> <textarea name="content" value={content} onChange={(event) => setContent(event.target.value)}></textarea>
修复后的完整代码
import Link from "next/link"; import { client } from "@/libs/client"; import { useRouter } from "next/router"; import React, { useState } from "react"; export default function Update ({ blog }) { const router = useRouter() const id = blog.id; // 用blog数据初始化状态 const [title, setTitle] = useState(blog.title); const [content, setContent] = useState(blog.content); async function update(event) { event.preventDefault() client.update({ endpoint: "blogs", content: { title: title, content: content, }, contentId: id }).then((res) => { if (res.status === 401) { alert("Something wrong is happening") } else { alert("Editing is done") router.push(`/`) } }) } return ( <> <div className='main'> <h1 className=''>Edit page</h1> <div className="contents"> <div> <form onSubmit={ update }> <div> <h2>Here's title</h2> {/* 用value绑定状态 */} <input name="title" type="text" value={title} onChange={(event) => setTitle(event.target.value)} /> </div> <div> <h2>Contents</h2> {/* 用value绑定状态 */} <textarea name="content" value={content} onChange={(event) => setContent(event.target.value)} ></textarea> </div> <button type="submit"> <p>Submit</p> </button> </form> </div> </div> </div> </> ); } export const getStaticPaths = async () => { const data = await client.get({ endpoint: "blogs" }); const paths = data.contents.map((content) => `/blog/${content.id}/update`); return { paths, fallback: false }; }; export const getStaticProps = async (context) => { const id = context.params.id; const data = await client.get({ endpoint: "blogs", contentId: id }); return { props: { blog: data, }, }; };
内容的提问来源于stack exchange,提问作者Noriaki Takamizawa
相关产品推荐
相关产品推荐

