Handling Errors in Full-Stack Applications (React.js & Node.js)

Error handling is one of the most important requirements in software development. It matters for either small or big projects because, without it, your users will be left wondering and guessing why certain actions did or did not happen. trust me, when errors are handled prematurely, it translates to bad user experience and hence continuous reduction of traffic to your application. While working on a Node.js API and react application, I realized that there are so many ways to prematurely handle errors and there are better ways to maturely deal with these mistakes. Hang in there, let me demonstrate what I am saying with a real application. you can look at the source code. The application is a full-stack crud app used to manage employees with an API running on Node and client built with react. For the back-end, I am using express.js to manage routes, Sequelize ORM, and Sequelize-CLI to manage migrations and MYSQL as my database. for the front-end, I am using function-based react components with React hooks. I am also leveraging React context API to store data and react-router-dom to manage routes. I will try and handle errors for fetching a list of employees and display the appropriate message to a user.

Handling Back-End Errors

Express.js allows us to create route handlers that return a promise like so

the handler has a request and response object and an optional callback next function. Before I knew there is a better way to handle errors in Express.js, this is how I used to handle it.

If the findAll method rejects or throws an error, the catch block will handle it. from the screenshot above, you realize that we are generalizing all errors to be 404 and that is not true. what we really want is to return 404 status code and not found error message when the client hits this endpoint and finds no resources or server error (500) when something else happened. when searching for better ways, I found that express.js has a default error handler which actually runs when none of our error catching technique works. This error handler receives the error object from our routes through the next callback function. We can customize this error handler to meet our needs. This custom error handler is a middleware that is placed at the end of the middleware function stack (and after your routes please).

From the above screenshot, you can see that the handler takes in four arguments and I am more interested in the error object which contains errors reject or thrown by our route handler. All we now need to do is to create the error object with a message and status code and let catch and next callback function do the magic for us. We are using the http-errors package to help us easily create an error object. Our updated route should now look like below.

Handling Front-End Errors

When the native fetch API in our react app hits the above route handler, it is expecting to either return list of employees or an error message that explains why it couldn’t find anything. I will not go deep into how the Fetch API works but you can find more information here. Here is my version before I found that there is a better way.

from the screenshot, there is no absolute way our application will know something happened and our users will be kept in the dark waiting for something to happen. The reformed me will handle this in a better way by creating three objects in my state; employee, error, and isLoading. The employee object will contain a list of employees if found. the error object will contain errors from backend and isLoading is a boolean that determines if Fetch is still fetching data from the backend. Here is my state.

The interesting part about all this is how we fetch data from our API. Fetch API is promised-based and only rejects when there is a network error. When it resolves, the response object will contain some properties and we are interested in ok and statusText. In whichever way we take it, we have to find a way to activate the catch block to capture our errors. Here is how I do it now.

Note that when the response object is ok, it means we are expecting some good results but when it is false, it means it failed and we need to alert our users of what happened.
That is all for now. If you liked this article, join me and lets clap.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top