Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Only send values that have changed in formik onSubmit

I have a small table of data that is pre-filled by an api call on page load. Each row in the table has a facility name and an Enabled value which comes from the api call. If Enabled == true the checkbox is shown as checked.

I have a couple checkboxes that are grayed out because of a condition in which it cannot be changed at all so there's a readOnly attribute on the field.

Onto my question, for brevity I condensed the list of facilities shown in the table, but in reality there could be X amount of facilities. In my onSubmit function I only want to send the facility name and enabled value if they have been selected/deselected instead of sending the entire list every time submit is pressed.

Ideally I want the shape of the data sent to look like so:

{
    facilityName: "Backup Restore",
    enabled: true
}

Now, I have been able to isolate JUST the facilityName and enabled value but I cannot figure out to only include the values that have been changed in the form. Like I said above, not every single facility name and enabled key/value should be sent every time submit is pressed just the ones that have been changed.

This is what I currently have(and can be seen in the sandbox below) in my onSubmit function

         <Formik
          enableReinitialize
          initialValues={{
            facilities: loggingFacilities
          }}
          onSubmit={async (values, { setSubmitting }) => {

            alert(JSON.stringify(values, null, 2));
            try {

              setLoggingFacilities(values.facilities);
              const valuesToSend = values.facilities.map(facility => {
                return {
                  key: facility.facilityName,
                  value: facility.enabled
                };
              });
              .....

I have a codesandbox here

like image 819
DJ2 Avatar asked Jan 06 '20 22:01

DJ2


2 Answers

From the second param of your onSubmit callback, you can access props, so you could diff values against props.initialValues or however you have called the prop you use to initialize the form.

Actually, that's the suggestion from Jared Palmer:

You can compare initialValues and values within handleSubmit / onSubmit.

Using Array.prototype.filter() it would look something like this:

onSubmit={async (values, { props, setSubmitting }) => {

  // Let's assume this has the same format as `values.facilities`:
  const { initialValues } = props;

  try {
    setLoggingFacilities(values.facilities);

    const valuesToSend = values.facilities.filter((facility, i) => {
      // Let's send only those that have just been disabled or enabled:
      return facility.enabled !== initialValues[i].enabled;
    }).map((facility) => ({
      key: facility.facilityName,
      value: facility.enabled
    }));

    // ...

  } catch(err) { ... }

}
like image 172
Danziger Avatar answered Oct 28 '22 03:10

Danziger


Try this:

const getChangedValues = (values, initialValues) => {
  return Object
    .entries(values)
    .reduce((acc, [key, value]) => {
      const hasChanged = initialValues[key] !== value

      if (hasChanged) {
        acc[key] = value
      }

      return acc
    }, {})
}
like image 35
randomKek Avatar answered Oct 28 '22 03:10

randomKek