You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编辑个人资料页面提交未修改内容时清空数据库字段问题排查

编辑个人资料未修改提交时清空数据库字段的解决方案

问题根源

你碰到的问题核心是前端表单状态和用户实际数据不同步:

  • 页面加载后,你通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:00:59