编辑个人资料页面提交未修改内容时清空数据库字段问题排查
编辑个人资料未修改提交时清空数据库字段的解决方案
问题根源
你碰到的问题核心是前端表单状态和用户实际数据不同步:
- 页面加载后,你通过
getUser获取了用户数据并存在user状态里,但formData始终是初始的空字符串值 - 输入框用
defaultValue显示用户数据,但这是非受控组件,用户没修改时,formData里的字段仍然是空 - 提交时把空值传给后端,后端用
$set直接覆盖数据库字段,导致原有数据被清空 - 性别单选框的
checked依赖formData.gender_identity,初始为空,所以用户原有性别不会被选中,提交时也会传空值清空数据库
前端修复方案
核心是让formData初始值和用户数据同步,把表单改成受控组件,确保状态和输入完全绑定:
const EditProfile = () => { const [cookies, setCookie, removeCookie] = useCookies(null); const userId = cookies.UserId; const [user, setUser] = useState(null); const [formData, setFormData] = useState({ user_id: userId, first_name: "", gender_identity: "", about: "" }); let navigate = useNavigate(); const getUser = async () => { try { const response = await axios.get("http://localhost:4000/user", { params: { userId }, }); const userData = response?.data; setUser(userData); // 获取用户数据后同步更新formData,让表单初始值和用户数据一致 setFormData(prev => ({ ...prev, first_name: userData.first_name, gender_identity: userData.gender_identity, about: userData.about })); } catch (error) { console.log(error); }; }; useEffect(() => { getUser(); }, []); const handleSubmit = async (e) => { console.log("submitted"); e.preventDefault(); try { const response = await axios.put("http://localhost:4000/editprofile", { formData, }); console.log(response); if (response.status === 200) navigate("/dashboard"); } catch (err) { console.log(err); } }; const handleChange = (e) => { const value = e.target.type === "checkbox" ? e.target.checked : e.target.value; const name = e.target.name; setFormData((prevState) => ({ ...prevState, [name]: value, })); }; return ( <> <Nav minimal={true} setShowModal={() => {}} showModal={false} /> <div className="onboarding"> <h2>EDIT </h2> <form onSubmit={handleSubmit}> <section> <label htmlFor="first_name">First Name</label> <input id="first_name" type="text" name="first_name" required={true} value={formData.first_name} {/* 改用value绑定,变成受控组件 */} onChange={handleChange} /> <label>Gender</label> <div className="multiple-input-container"> <input id="man-gender-identity" type="radio" name="gender_identity" value="man" onChange={handleChange} checked={formData.gender_identity === "man"} /> <label htmlFor="man-gender-identity">Man</label> <input id="woman-gender-identity" type="radio" name="gender_identity" value="woman" onChange={handleChange} checked={formData.gender_identity === "woman"} /> <label htmlFor="woman-gender-identity">Woman</label> </div> {/* 补全之前缺失的闭合标签 */} <label htmlFor="about">About me</label> <input id="about" type="text" name="about" required={true} value={formData.about} {/* 改用value绑定 */} onChange={handleChange} /> <input type="submit" /> </section> </form> </div> </> ); };
后端优化方案(可选,双重保障)
即使前端处理到位,后端也可以只更新有实际变化的字段,避免意外清空:
app.put('/editprofile', async (req, res) => { const client = new MongoClient(uri) const formData = req.body.formData try { await client.connect() const database = client.db('app-data') const users = database.collection('users') const query = {user_id: formData.user_id} // 先查询用户原有数据 const existingUser = await users.findOne(query) // 只生成有变化的更新字段 const updateFields = {} if (formData.first_name !== existingUser.first_name) { updateFields.first_name = formData.first_name } if (formData.gender_identity !== existingUser.gender_identity) { updateFields.gender_identity = formData.gender_identity } if (formData.about !== existingUser.about) { updateFields.about = formData.about } // 如果没有字段需要更新,直接返回 if (Object.keys(updateFields).length === 0) { return res.json({ modifiedCount: 0 }) } const updateDocument = { $set: updateFields } const updatedUser = await users.updateOne(query, updateDocument) res.json(updatedUser) } finally { await client.close() } })
内容的提问来源于stack exchange,提问作者Mike_Alpha_Romeo_Charlie
相关产品推荐
相关产品推荐

