Best Practices in React Applications

10 Things Not to Do When Building React Applications

What to avoid based on my experiences working in production

Jun 29, 2019 · 8 min read
Image for post
Image for post
Photo by Alex Qian from Pexels

React is a popular tool for developing, and I’m sure you React fans out there are feeling blessed to be able to get your hands dirty with such a great library.

Unfortunately, nothing in life is perfect, and React is no different. React comes with its own set of gotchas — and some of them can potentially become severe problems for your applications if you don’t take care of them now.

Here are 10 things not to do when building React applications.

1. Spending Too Much Time in Your Own Private World

Image for post
Image for post
Photo by Bruno Thethe from Pexels

If you’re spending too much time coding and not taking the time to read about what’s happening in the community, you risk running into bad coding practices that have been reported in the community. You might end up using those bad coding practices code 20 times before you finally find out in a Medium post that they are bad.

When that happens, you’ll have to go back and refactor those 20 code implementations because you found out too late. While you’re doing that, everybody else will move ahead of you. They’ll move onto newer coding news while you’re still catching up.

When React released hooks, I was so excited. I began building a bunch of mini projects to play with these new toys that everybody was all hyped up about. After reading in a couple of sources that hooks were going to be stable, I began implementing them more seriously in my projects. I was using useState and useEffecteverywhere.

Then I came across someone linking to this tweet, which lead to me doing some more research about useReducer. That 30 minutes of research was enough to make me go back and refactor a good amount of code.

2. Using .bind (Not Class Component Constructors)

I think the majority of us React developers are aware that we should .bind our class methods if we want to reference this to access their own class instance inside their methods. (Unless you’re using a transpiler to transpile your class properties and methods.)

That’s great, and I also prefer declaring class methods with arrow functions.

But what I’m going to talk about is inline functions. These are functions that are defined within the render method of a react component and passed down as a prop to a child component.

When inline functions are defined in the render method, React begins to designate a new function instance each time the component re-renders. This is known to cause performance issues due to wasteful re-rendering.

Let’s take a look at this example:

We know that onClick={() => sayWhereTheMoneyIs("I don't know")} and onClick={() => showThemTheMoney(0.05)} are inline functions.

I’ve seen a couple of tutorials (including one from Udemy) that encourage doing this:

This seems like it caches the reference and avoids unnecessary re-renders because they aren’t using arrow inline functions in the render method. But they are actually still creating new functions on each render phase!

If you were following the community in the React ecosystem during the times when class components were trending, you may have already known that.

However, since React hooks were released, there has been less talk about .bind since class components are becoming less popular. When .bind was talked about, people would usually discuss binding class methods. And to add on to that, the examples above aren’t even binding to class methods at all. That makes it even harder to notice the consequences here if you aren’t careful.

Newcomers should especially be aware of this anti-pattern!

3. Passing Dynamic Values as Keys to Children

Have you ever felt forced to provide unique keys to children that were being mapped over? It’s good to provide unique keys:

Now pretend that some tovalues in items1 happen to be the same as some in items2.

When some people want to refactor a similar component to this, they end up doing something like this:

This does get the job done by providing unique keys to each child. But there are two things wrong:

  1. Not only are we making React do unnecessary work with generating unique values, but we’re also ending up recreating all of our nodes on every render because the key is different each time.
  2. The key concept in react is all about identity. And to identify which component is which, the keys do need to be unique, but not like that.

Something like this works a little better:

Now we should feel confident that each item will have their own unique key value while preserving their identity.

4. Declaring Default Parameters Over Null

I was once guilty of spending a good amount of time debugging something similar to this:

Inside our App component, if dates ends up being falsey, it will be initialized with null.

And when we run the code, if you’re like me, your instincts tell you that items should be initialized to an empty array by default if it was a falsey value. But our app will crash when dates is falsey because items is null. What?

Default function parameters allow named parameters to become initialized with default values if no value or undefined is passed!

In our case, even though null is falsey, it’s still a value!

This mistake caused me to spend a lot of time debugging the code, especially when the null value was coming from the redux reducers! Ugh.

5. Leaving Repetitive Code Untouched

It can be tempting to copy and paste code when you’re rushing to push out a fix. Sometimes, doing this can be the quickest solution.

Here’s an example of repetitive code:

Now’s a good time to begin thinking about how to abstract these components in a way where they can be reused multiple times without changing the implementation. If there was a styling issue in one of the Grid components relative to their surrounding Grid containers, you’d have to manually change every single one of them.

A better way to code this is by abstracting out the repeated parts and pasting in the props that are slightly different:

So now if your boss ends up changing his mind and wants to make all of these sections about 300px in height, you only have make a change in one place.

Now, I’m not recommending a solution like this if you’re looking to make a component supporting several use cases. This is for specific uses where we know it’s going to be re-used only in that environment. A more dynamic re-usable solution for SectionContainer that supports multiple use cases would have probably been coded to be more generic. You should still do this without changing the implementation:

That way, we now allow the developer to optionally extend any part of the components as needed while retaining the underlying implementation.

6. Initializing Props in the Constructor

When you initialize state in the constructor:

You might run into bugs. That’s because the constructor is only called once, which is the time the component first gets created.

The next time you try to change props, the state will retain its previous value because the constructor won’t be getting called in re-renders.

If you haven’t come across this problem yet, I hope this helps you! And if you were wondering how to make the props synchronize with the state, a better approach would be something like this:

7. Conditional Rendering With &&

A common gotcha when conditionally rendering components is using the && operator.

React will attempt to render anything you provide as the alternative output if a condition doesn’t meet its requirements. As such, when we look at this:

This will actually render a number 0 on the screen when items.length is empty. JavaScript considers the number 0 as a falsey value, so when itemsis an empty array, the && operator won’t be evaluating the expression to the right of it. It will just return the first value.

What I usually do if I want to keep the syntax is use double negation:

That way, if itemsis an empty array, React will not render anything on the screen if the evaluated output is a boolean.

8. Not Spreading Previous States

Something that can occasionally creep up on my list of bugs comes from carelessly implementing state update logic.

A recent situation involved React hooks, specifically a useReducer implementation. Here’s a basic example of this becoming an issue:

When the something function invokes and copies the state over, the underlying itemsproperty has not changed. When we mutate it using .splice, this mutates state.items and will introduce bugs.

Be especially weary about this in larger codes. We could all probably get past a small example like the one above, but when things get messy, this always has to be kept in mind. It’s easy to forget about this, especially when you’re being pressured to ship code to production!

9. Not Explicitly Passing Down Props to Child Components

Generally, it’s recommended that you be explicit in the props you pass down to child components.

There are a few good reasons for this:

  1. You have an easier debugging experience.
  2. You as a developer know what is being passed to each child.
  3. Other developers will also know and will have an easier time reading the code.
  4. It’s easier to understand what a component will do.
  5. Another great thing about passing down props explicity is that when you do this, it’s also documenting your code in a way where everyone understands without needing formal documentation. And that saves time!
  6. There will be fewer props needed in order to determine if the component should re-render or not.

There can be some pretty neat use cases for spreading all the props. For example, if a parent quickly needed one or two things before passing the props down to child components, it can be easy for them (and you) to do so:

Just make sure you don’t find yourself in a situation like this:

And if you do, consider splitting the component parts to separate components so that it’s cleaner and more customizable.

10. Prop Drilling

Passing down props to multiple child components is what they call a code smell.

If you don’t know what prop drilling is, it means when a parent passes down props to multiple levels of components deep down the tree.

Now, the problem there isn’t the parent or the child. They should keep their implementation the same. It’s the components in the middle that might become an issue in your React apps.

That’s because now the components in the middle are tightly coupled and are exposed to too much information that they don’t need. The worst part is that when the parent re-renders, the components in the middle will also re-render. This creates a domino effect for all the child components down the chain.

A good solution is to use context instead. Or alternatively, redux for props (which consequently are going to be serialized).

That concludes the end of this post. I hope you found this article helpful!

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

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