Clean Architecture — Mapping and Displaying Server-Side Errors With Formik in React Client App
Discussing how to properly map server-side errors to individual inputs and display the errors, which complements client-side validations using Formik and Yup.
Handling server-side errors on the client-side is always tricky as it can be hard to map the errors to individual form inputs and display them accordingly. When building a React web application, using Formik and Yup allows us to handle client side errors pretty intuitively, but it is still not straightforward to handle server side errors.
In fact, there is an open issue on the Formik GitHub repo asking how to properly track and display server-side errors, in addition to client-side validation errors. While there are lots of discussions under this topic, this issue apparently is more difficult than it looks to address at the abstraction level. Even though the ticket was created in 2017, it is still open as of this writing in Nov. 2020!
The Formik author, Jared Palmer, recommends, quote to quote, “Write an small function that transforms your backend error into same shape as formik’s errors and then call setErrors”.
The goal of this article is to showcase how the recommendation from Jared can be implemented in a React web application using Formik, Yup, and TypeScript. The demo page is a form for creating a todo item.
First, let’s see how a form with just client end validation works using Formik and Yup. In the screenshot below, both Title and Category inputs are required inputs using validation schema defined using Yup. These are client end errors that nicely line up with their individual inputs.
Here is the sample code used to build the form with client end errors using Formik and Yup.
Second, let’s handle generic server side error message, which does not bind to any specific form input. In the screenshot below, you will notice a red toaster with message “Error: One or more validation errors occurred.”. The message itself is from the 400 error response from the server (see console). In this case, title “test” already exists in the database and the API returned a 400 bad response with title “One or more validation errors occurred.”.
Uncommenting the following lines from the code sample above would allow us to display the generic error message in the toaster at the bottom of the screen.
Last step, how do we map the errors array from the server-side 400 response to the individual form inputs and render them accordingly? Based on Jared’s recommendation at the very beginning of this article, let’s format the server errors into the same shape as the Formik errors and set it, and Formik will know how and where to display them. In the screenshot below, notice “Title must be unique” is nicely displayed together with Title input. Lovely!
All we had to do was to uncomment these lines in the sample code. Notice in the console, “Title” in errors is capitalized, but Formik use camel case, so we have to camel case all keys in the errors object before we ask Formik to setErrors, which in return trigger the error messages to render on the form.
For best user experience and application performance, it is good practice to catch known validation errors on the client end so that they don’t hit the server. Formik plus Yup do it really well for a React application. Properly handling server side errors greatly improves the user experience as the user would know exactly what input field they need to fix, compared to only seeing a generic error “Something went wrong! Please contact site administration!”.
This whole starter project can be used to build a React web application backed by a REST API built using ASP.NET Core and Cosmos DB. Feel free to use the whole starter project or part of it to kick start your next exciting adventure! Project Link: Clean Architecture with partitioned repository pattern using Azure Cosmos DB
Many thanks for reading! Enjoy making the world a better place with clean code!