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

React中使用Axios发送put请求仅更新特定字段的实现问题

解决方案

前端调整

  • 首先修复初始化逻辑:原有useEffect会在页面加载时自动触发更新请求,改为加载时拉取当前公司的原有数据填充表单,避免用户需要重复填写未修改的字段
  • 请求体过滤空字段:构造请求参数时仅保留用户有输入的非空字段,空值字段不提交,避免把不需要修改的字段以空值传给后端

修改后的前端代码示例:

function UpdateCompany(props): JSX.Element {

  const history = useHistory();
  const [name , setName] = useState('');
  const [email , setEmail] = useState('');
  const [password , setPassword] = useState('');

  // 页面加载时拉取原有公司数据填充表单
  useEffect(() => {
    const fetchCompany = async () => {
      const res = await axios.get(globals.adminUrls.getCompany + props.location.state.id)
      const company = res.data
      setName(company.name)
      setEmail(company.email)
      setPassword(company.password)
    }
    fetchCompany()
  }, [props.location.state.id]);

  async function formData() {
    try {
      // 仅收集非空字段作为请求参数
      const payload = {}
      if(name.trim()) payload.name = name
      if(email.trim()) payload.email = email
      if(password.trim()) payload.password = password

      const response = await axios.put<CompanyModel>(globals.adminUrls.updateCompany + props.location.state.id, payload);

      const updated = response.data;
      store.dispatch(companyUpdatedAction(updated));
      notify.success(SccMsg.COMPANY_UPDATED)

    }
    catch (err) {
      notify.error(err);
    }
  }

  const handleSubmit = (e) => {
      e.preventDefault();
      formData();
  }

  return (
    <div className="custom-field">
      <h2>Update Company</h2>
      <div>
        <form onSubmit={handleSubmit} >
          <label>Name</label>
        <input type="text" name="name" value={name} onChange={(e)=>{setName(e.target.value)}}/>
        <label>Email</label>
        <input type="text" name="email" value={email} onChange={(e)=>{setEmail(e.target.value)}}/>
        <label>Password</label>
        <input type="text" name="password" value={password} onChange={(e)=>{setPassword(e.target.value)}}/>

        <input  type="submit" name="submit"/>
        </form>
      </div>

    </div>
  );
}

export default UpdateCompany;

后端调整

原有逻辑会直接将DTO全量转换为DAO覆盖数据库数据,需要改为增量更新逻辑:先查询数据库中已有的公司数据,仅将DTO中不为null的字段覆盖到已有对象上,其余字段保留原有值再保存。

修改后的Service代码示例:

public void updateCompany(@Valid int id, CompanyDto companyDto) throws DoesNotExistException, AlreadyExistsException {
    // 先查询现有公司数据
    Company existingCompany = compRepo.findById(id)
            .orElseThrow(() -> new DoesNotExistException("Company does not exist"));
    // 仅更新非空字段
    if (companyDto.getName() != null) {
        existingCompany.setName(companyDto.getName());
    }
    if (companyDto.getEmail() != null) {
        existingCompany.setEmail(companyDto.getEmail());
    }
    if (companyDto.getPassword() != null) {
        existingCompany.setPassword(companyDto.getPassword());
    }
    // 校验字段重复等逻辑可以放在这里执行
    compRepo.saveAndFlush(existingCompany);
}

如果项目使用MapStruct做对象映射,可在Mapper接口上添加配置nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE,实现自动忽略null值的字段映射,无需手动编写if判断逻辑。

如果业务场景需要支持将字段清空为null,可取消前端的空值过滤,仅保留后端的增量更新逻辑,前端主动传null的字段后端会更新为null,未传的字段保留原有值。语义上增量更新更推荐使用PATCH请求,你也可以将请求方法从PUT改为PATCH更符合REST规范。

内容的提问来源于stack exchange,提问作者Shai Ace

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:24:04