Formik forms and API integration

Image by René Beck from Pixabay

In a previous article, I detailed out how to wrangle large Formik forms using sub forms and composing them within a larger form. In typical enterprise applications, a large form’s goal is to capture user input that will be sent to a server via REST or GraphQL. The biggest challenge we face is dealing with nested API data that doesn’t bend well within a flat form. A typical use case is like this:

  • API returns a business object and hydrates the form with it.
  • User edits this and submits the values.
  • Form submit action performs an API call directly or indirectly using the edited values.

The struggle is to match Formik’s JSON values to the API’s payload and vice versa. The UX form designs may not directly align with the API. Compounding to the issue is that the API s are always not necessarily UI friendly. Some are spec-ed out for public consumption and not tailored for the user experience. This adversely affects the developer experience. Here is a strategy that can solve this gracefully:

Form values and API payload object shapes do not have to align 100%

What we needed are data transformations between these two entities.

toFormValues() and toApiPayload() are simple, pure data transformation functions. They are very easy to write unit tests for.

Now, your form is free from API data restrictions and can cater to the UX design and the component library’s form fields. For instance, data that appears in a Select pulldown doesn’t have to be arm twisted to fit the Form requirements.

Using TypeScript

TypeScript interfaces are a must when you deal with complex data shapes. Without it, the chances of human errors are too much. I highly recommend it. Essentially your data types and functions would look like this:

interface IApiValues {
user: {
id: string;
fullName: string;
}
}
interface IFormValues {
userId: string;
userName: string;
}
type toFormValuesType = (apiData: IApiValues) => IFormValues;type toApiPayloadType = (values: IFormValues) => IApiValues;

Implement your transformers:

const toFormValues: toFormValuesType = apiData => ({
userId: apiData.user.id,
userName: apiData.user.fullName
});
const toApiPayload: toApiPayloadType = values => ({
user: {
id: values.userId,
fullName: values.userName
}
});

Now plug these into your Formik form:

const submitForm = (values: IFormValues) => { 
submitToApi(toApiPayload(values));
}
<Formik
initialValues={toFormValues(apiData)}
onSubmit={submitForm}
children={YourFormContainer}
/>

The solution is quite simple. Yet, it keeps your forms clean by delegating transformation to the helper functions. They can stay true to the UX design and the available input components. You don’t have to litter your form code with data wrangling all over the place. Plus your data transformations become very unit testable.

describe("form/api data transformations", () => {  const apiData: IApiValues = {
user: {
id: "1234",
fullName: "Naroth"
}
};
const formData: IFormValues = {
userId: "1234",
userName: "Naroth"
};
it("should transform correctly", () => {
expect(toFormValues(apiData)).toEqual(formData);
expect(toApiPayload(formData)).toEqual(apiData);
});
// Alternatively you could do it in one shot
// But it is better to test them individually
it("should transform back and forth correctly", () => {
expect(toApiPayload(toFormValues(apiData))).toEqual(apiData);
});
// You can also use snapshot testing to keep a reference
// of the object. It helps to understand the logic and aids
// debugging.
it("toFormValues works", () => {
expect(toFormValues(apiData)).toMatchSnapshot();
});
});

This example applies to Formik but you can apply the same strategy with another Form handler library in a similar fashion.

--

--

--

Frontend Architect, San Jose, CA

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Aura theme 2.0 is out now 🤩

How You Can Ban Error-Prone Loops From Your JavaScript Code Entirely

How JavaScript works: the different ways of declaring a function + 5 best practices

The Basics of NPM

Task 7.2

Create the Time Warp effect in Lens Studio

Create a Time Warp or Screen Scanner Pro effect in Lens Studio

A Beginner’s Guide To Data Types In JavaScript

How to Create and Publish a Package to NPM Registry

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rajesh Naroth

Rajesh Naroth

Frontend Architect, San Jose, CA

More from Medium

Login in with Google inside your ReactJS Application.

What is a Component in React JS?

ReactJS — Prop Drilling