Search code examples
javascriptreactjstypescriptformikhttp-method

TypeScript - Send optional field on POST only when there is value


I am using Formik, in my React application. I have a simple form with 3 fields. I am doing 2 operations with that form. Add/Edit Resources.

My Problem is that one field is optional. Meaning I should never send it, if its value is null. Currently, I send an empty string which is wrong.

I am using TS-React-Formik, and here is my code for the handleSubmit method:

interface IValues extends FormikValues {
  name: string;
  owner?: string;
  groups: string[];
}

interface CreateAndEditProps {
  doSubmit(service: object, values: object): AxiosResponse<string>;
  onSave(values: IValues): void;
}

handleSubmit = (values: FormikValues, formikActions:FormikActions<IValues>) => {
    const { doSubmit, onSave, isEditMode } = this.props;
    const { setSubmitting } = formikActions;
    const payload: IValues = {
      name: values.name,
      groups: values.groups,
      owner: values.owner
    };
    const submitAction = isEditMode ? update : create;
    return doSubmit(submitAction, payload)
      .then(() => {
        setSubmitting(false);
        onSave(payload);
      })
      .catch(() => {
        setSubmitting(false);
      });
  };

I thought a simple if statement would work, and while it does, I do not like it at all. Let me give you an example of why. If I add 2 more optional fields, as I am about to do, in a similar form, I do not want to do several if statements to achieve that.

If you could think of a more elegant and DRY way of doing it, It would be amazing. Thank you for your time.


Solution

  • Look at the removeEmptyKeys() below. It takes in an Object and removes the keys that have empty string.It mutates the original Object, please change it accordingly if you expect a diff behaviour.

    In your code after defining payload, I would simply call this method , removeEmptyKeys(payload)

    Also it will resolve your if else problem.

    removeEmptyKeys = (item)=>{
    Object.keys(item).map((key)=>{
    if(payload[key]===""){
    delete payload[key]}
    })}
    
    var payload = {
    one : "one",
    two : "",
    three : "three"
    }
    removeEmptyKeys(payload)

    Please mark it as resolved if you find this useful.

    For your code :

    const removeEmptyKeys = (values: IValues): any => {
    Object.keys(values).map((key) => { 
    if (payload && payload[key] === "")
    { delete payload[key] } }) 
    return values; 
    }