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

React Hook Form中获取字段变脏前的原始值方法

如何获取React Hook Form中图片字段的原始值以删除旧图片?

我有一个Profile组件,从Context中获取用户数据并支持编辑。提交表单触发editProfile函数时,我通过dirtyFields.image判断图片是否已更改,如果是就将新图片上传到Firebase,但需要删除之前的旧图片,却不知道怎么获取旧图片的原始值。

代码示例:

import { useContext } from "react";
import AuthContext from "../../context/Auth-context/AuthContext";
import { useForm } from "react-hook-form";
import useFilePreview from "../Helpers/useFilePreview";
import { post } from "../Helpers/post";
import { uploadImageToFirebase } from "../Helpers/uploadImageToFirebase";

function Profile() {
  const { user } = useContext(AuthContext);
  const form = useForm({
    defaultValues: {... , image: user?.image}
  });
  const { register, handleSubmit, watch, getValues, formState: { dirtyFields } } = form;
  const image = watch("image");
  const imageToDelete = getValues("image"); // 这里拿到的是更新后的值,不是旧值
  const [imagePreview] = useFilePreview(image);

  const editProfile = async (data) => {
    let url;
    if (dirtyFields.image) {
      url = await uploadImageToFirebase(data.image[0]);
      // 需要在这里获取旧图片URL来删除,但不知道怎么拿
    }
    data.image = url || image;

    post(`http://localhost:8000/api/edit-profile/${data.id}`, "PUT", {...data});
  };

  return (
    <form onSubmit={handleSubmit(editProfile)}>
      <img src={imagePreview} />
      <label>Change profile picture</label>
      <input {...register("image")} type="file" accept="image/*" />
      <button>Save changes</button>
    </form>
  );
}

export default Profile;

我尝试用getValues("image")存储旧图片,但它会随着表单更新返回新值,无法拿到修改前的原始URL,该怎么解决?


解决方案:直接保存组件初始化时的原始图片值

因为表单的defaultValues.image是从user?.image来的,而user来自Context,组件初始化时的user.image就是旧图片的原始URL,直接把这个值存下来即可,不会随表单变化而改变。

修改后的关键代码:

function Profile() {
  const { user } = useContext(AuthContext);
  // 保存初始的旧图片URL,组件挂载时只会赋值一次
  const originalImage = user?.image; 

  const form = useForm({
    defaultValues: {... , image: originalImage}
  });
  // ... 其他代码不变

  const editProfile = async (data) => {
    let url;
    if (dirtyFields.image) {
      url = await uploadImageToFirebase(data.image[0]);
      // 在这里使用originalImage调用删除旧图片的方法
      // await deleteImageFromFirebase(originalImage);
    }
    data.image = url || originalImage;

    post(`http://localhost:8000/api/edit-profile/${data.id}`, "PUT", {...data});
  };

  // ... 其余代码不变
}

为什么之前的方法不行?

getValues("image")返回的是当前表单字段的最新值,当用户选择新图片后,表单的image字段会更新为新的File对象(或预览地址),所以无法拿到修改前的原始URL。而直接从Context的user中保存初始值,这个变量在组件挂载后就不会再变化,始终是旧图片的原始地址。


内容的提问来源于stack exchange,提问作者Morgana Freeman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:33:16