3 Ways to Write Elegant JavaScript Code

It’s time to put an end to spaghetti code.

Zachary Dorcinville
JavaScript in Plain English

--

Photo by Christopher Robin Ebbinghaus on Unsplash

Whenever I finish building a project or take a look at some older code, I always try to find ways to refactor and improve readability. Methods of doing this can include writing custom React hooks, wrapping repeated code into subroutines, and others. In this article, I’ll be sharing three common methods to modularize and improve the maintainability of your code. Let’s dive in.

1. Use TypeScript

This may come as an eye-roller for some, but TypeScript alleviates many of the issues that make JavaScript an unsafe language in some cases. It also makes the intentions of your code clearer. Let’s take a look at a JavaScript example of a simple React component People:

We can see here that People accepts peopleList as props, which is a list of objects each representing a person which will be rendered as a <ListItem />. All of this is fine, but what if a property is missing from one of the people? What if a person has undefined as their occupation or salary? A lot of you might be thinking that we can just use prop-types to handle this, but in my opinion, TypeScript provides a more elegant solution. Let’s look at the same People component, written in TypeScript:

In this example, we’ve defined an interface Person with optional properties (denoted with ?) to inform the compiler that a person in peopleList might only contain a subset of the properties in Person. We’ve also defined a PeopleProps interface that specifies the type of prop People should receive, which is a Person array. As a result of this, the People component is more flexible and robust.

2. Use IIFEs

If you’re familiar with Immediately Invoked Function Expressions (IIFE), then you definitely know how useful they can be as a clean way to compose two statements into one. Let’s say you wanted to initialize an array with some external data:

In this example we’ve defined a function initList which returns an array containing the external data. We then call the function and store the result in dataList. It’s not that there’s anything wrong with this code, but it could be written more elegantly, like so:

Here, we save a few lines by assigning dataList to an anonymous function that is immediately invoked.

3. Separation of Concerns

It is always important to separate the concerns of functionality in a codebase, especially when working with projects of increasing complexity. It is typically not ideal to have a function perform multiple tasks at once, especially if they are in no relation to each other. Let’s analyze a bad React example of a component Example that is dependent on some external API data:

The reason why this is a bad example is because the Example component should only be responsible for displaying the data on the screen, not fetching the external data. This creates clutter and makes the component harder to debug. Fortunately, we can fix this by writing our own hook that contains the logic for making a post request. This hook will be a function that accepts a url and options, makes the post request, and returns the data like so:

Now that all of the logic to call the API is in this custom hook, our Example component now looks like this:

With usePost abstracting away the post request logic, the Example component is now only responsible for displaying the data. The codebase just became much more maintainable by making this change.

If you made it here, thanks for reading! I hope you found this post insightful. Enjoy the rest of your day.

More content at plainenglish.io

--

--