【问题标题】:React - Axios put request to update only specific fieldsReact - Axios 提出仅更新特定字段的请求
【发布时间】:2021-11-21 14:26:40
【问题描述】:

对于使用后端的项目做出反应和工作相对较新。 基本上所有功能都相应地工作,但是,我有点不确定如何实现put 请求,该请求允许我只向后端发送特定值。

会发生什么: 当我向update 一家公司发送请求时,它要求我填写所有fields。如果我将字段留空,它会将它们作为空值发送。

E.G:

company 具有姓名、电子邮件、密码等字段。 我想更新 ONLY email 字段而不更改其他字段。

组件:

function UpdateCompany(props): JSX.Element {

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

  async function formData() {
    try {

      const response = await axios.put<CompanyModel>(globals.adminUrls.updateCompany + props.location.state.id, {
        name: name,
        email: email,
        password: password
      });

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

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

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

  useEffect(() => {
    if (skipCount) setSkipCount(false);
    if (!skipCount)  formData();

}, []);

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

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

    </div>
  );
}

export default UpdateCompany;

希望我的问题很清楚。

谢谢。

后端控制器:

@PutMapping(value = "update/company/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @Override
    public void updateCompany(@PathVariable int id, @RequestBody CompanyDto companyDto) throws DoesNotExistException, AlreadyExistsException {
        adminService.updateCompany(id, companyDto);

后端服务:

 public void updateCompany(@Valid int id, CompanyDto companyDto) throws DoesNotExistException, AlreadyExistsException {

Company companyDao = companyMapper.toDao(companyDto);

if (!compRepo.existsById(id))
    throw new DoesNotExistException("Company does not exist");

companyDao.setId(id);

compRepo.saveAndFlush(companyDao);

【问题讨论】:

  • 不是很清楚是什么问题
  • @GiorgiMoniava 抱歉,如果我不清楚,目前如果我填写表单字段并尝试仅更新 1 参数,所有其他人将是 null 并相应更新,我想选择能够仅更新specific 字段,而其余字段不转为null。希望我很清楚。
  • 好吧,如果您只想更新电子邮件,那么您可以只发送电子邮件作为PUT 请求正文中的参数。我不太确定目前是什么阻碍了您。
  • @Salvino 我希望用户能够更新所有3 选项。但也可以选择仅更新选定字段而不更改其余字段。到目前为止,如果我不更新特定字段。它将以null 发送,我正在努力避免这种情况。
  • 是的,我明白了。所以它可以通过一个简单的if 条件来解决。如果任何属性值等于 null,请不要将其放在请求正文中。因此,如果电子邮件已填充,电子邮件将在请求正文中发送。如果填写了电子邮件和姓名,电子邮件和姓名将在请求正文中发送。

标签: reactjs axios react-hooks put


【解决方案1】:

只需使用简单的if 条件来执行空检查,同时填充PUT 请求正文。您可以通过以下方式进行:

async function formData() {
    try {
     const data = {};
     if(name) data.name = name; 
     if(email) data.email = email;
     if(password) data.password = password
     
     const response = await axios.put<CompanyModel>(globals.adminUrls.updateCompany + props.location.state.id, data);

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

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

【讨论】:

  • 我认为这将取决于端点 api。 OP 似乎在说的是,如果他为这三个属性之一发送 null ,它将不会接受 put 请求。我可能是错的......我有点在推断。
  • 这给了我同样的结果。如果我不添加字段,则返回为null
  • 啊,这意味着您正在更新所有值,即使它们在后端不存在。好吧,这是后端的逻辑错误。您是否对更新条件中的列键进行了硬编码?您应该只更新从最后传递给您的键值。不是整行。
  • @Salvino 我会尝试修复它。我还添加了一些信息。谢谢
  • 是的,我可以看到您正在使用弹簧。是原生的spring DAO吗?或者您正在使用其他一些 3rd 方 DAO?
【解决方案2】:

您需要获取当前值,然后使用它们设置初始状态。

这将具有在表单的输入字段中显示当前值的额外好处。出于这个原因,添加的调用是合理的,而且非常微不足道(公司信息多久会真正更新一次??)。

这样的事情可能会起作用:

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

// Get the current data, so you can set initial state with it.
useEffect(() => {
    const currentData = await axios.get<CompanyModel>();

    setName(currentData.name);
    setEmail(currentData.email);
    setPassword(currendData.password);

    if (skipCount) setSkipCount(false);
    if (!skipCount)  formData();
}, []);


async function formData() {

  .....

   const response = await axios.put<CompanyModel>(globals.adminUrls.updateCompany + 
      props.location.state.id, {
       name: name,
       email: email,
       password: password
     });

   const updated = response.data;

  ......

}

在此示例中,除非用户在表单中键入其他内容,否则您的值将保持不变。

您可能需要更改的唯一内容是获取请求,因为我不熟悉您的终点。

【讨论】:

  • 这不会无缘无故地向PUT 请求发送相同的旧值吗?我的意思是,如果您根本不打算更新它们或将它们更新为相同的旧值,为什么要将它们发送到后端?
  • @Salvino 不。如果用户不更改表单中的值,它只会发送相同的内容。一旦用户更改表单中的值,它将更新状态,并在参与 put 请求时发送更新值。
  • 是的,理想情况下,您应该在前端进行空检查,并且只在后端查询中修补从前端传递的属性。
  • @silencedogood 除了额外的async 调用之外,我同意这一点,但是,我可以给你我的控制器和服务的后端 api。会有帮助吗?
  • @salvino 我也同意这一点。我正试图以某种方式解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
  • 1970-01-01
相关资源
最近更新 更多