DEV Community

Cover image for Small Tips to Write Better React Code
Juan Cruz Martinez
Juan Cruz Martinez

Posted on • Originally published at livecodestream.dev on

Small Tips to Write Better React Code

Today we are going to talk about some of my favorite tips, which are super easy to implement or to follow, and that can make your JavaScript code cleaner. Also keep in mind some of the things we are going to learn today apply to JavaScript in general, though the article will focus on React.


Object destructuring

To get started we will review object destructuring, one of my favorites actually, that can help to keep the code small, clean, and elegant. This topic I love so much that I actually made a whole post about it here: Write Cleaner Code By Using JavaScript Destructuring.
Destructuring allows you to break down complex structures into simpler parts. Let's take a look at an example:

const { title } = props
console.log(title);
Enter fullscreen mode Exit fullscreen mode

A common place where React developers use this technique is with props. Though some people may argue that you lose context when you split the variables, it is usually the case in React, that the context is inherited by the component itself. Let's take a look at an example to show what I mean.

First, let's write a simple component to show Task information on the screen:

function TaskView(props) {
    return (
        <h1>{props.task.title}</h1>
        <p>{props.task.description}</p>
        <span>{props.task.completed ? 'Completed' : 'Pending'}</span>
    )
}
Enter fullscreen mode Exit fullscreen mode

It is indeed very simple, however, look at how we repeat props all the time, not very pretty. Let's look at another way to implement this:

function TaskView(props) {
    const task = props.task
    return (
        <h1>{task.title}</h1>
        <p>{task.description}</p>
        <span>{task.completed ? 'Completed' : 'Pending'}</span>
    )
}
Enter fullscreen mode Exit fullscreen mode

It's a bit better but still, we have tasks everywhere. Now someone who perhaps doesn't know destructuring may be tempted to do something like:

const title = props.task.title
const description = props.task.description
Enter fullscreen mode Exit fullscreen mode

which adds too much overhead to the declarations. Let's now see how the component looks like when using destructuring.

function TaskView(props) {
    const { title, description, completed } = props.task
    return (
        <h1>{title}</h1>
        <p>{description}</p>
        <span>{completed ? 'Completed' : 'Pending'}</span>
    )
}
Enter fullscreen mode Exit fullscreen mode

Now the code is very simple, we keep the JSX very clean from the rest, and we are still in context. It's perfectly understandable that when we say title we are talking about the Task as is what the component is all about. So keep your names clean, and structure well your components and you will love this feature.


Simplify your conditional statements

In this section, I want to talk about 3 different scenarios that can help us increase the readability of our code, and it's so easy, though many times we forget to do it.

Conditional execution

It is normal that at some point we need to run a statement only if a certain condition happens to be true. Usually, it goes something like:

const isFive = (num) => num === 5
if (isFive(5)) {
    console.log('It is the number five!')
}
Enter fullscreen mode Exit fullscreen mode

Now, there's nothing inherently wrong with that code, however, it can be simplified a bit:

const isFive = (num) => num === 5
isFive(5) && console.log('It is the number five!')
Enter fullscreen mode Exit fullscreen mode

Nice, but how does it work? JavaScript as many other languages, read conditional statements such us && or || in order from left to right, and they exit at the time they can invalidate the arguments.

Let's see an example of this with all conditionals:

const t = 1
t === 1 && t === 2 && t === 3
Enter fullscreen mode Exit fullscreen mode

In that example, JS will first take the first expression t === 1, since that expression is truthy and we have an and conditional, it needs to evaluate the next expression, as we need to guarantee they are all truthy. When it evaluates t === 2, which is falsy, it doesn't need to evaluate t === 3 at all, it can save that compute as we know the whole statement happens to be false.

Amazing! now let's learn something more about this. It is very common on the internet to see examples of this, however, did you know you can also use the || operator as well?

const isFive = (num) => num === 5
isFive(5) || console.log('It is the number five!') // does not execute the console.log
isFive(10) || console.log('It is not the number five!') // it executes the console.log
Enter fullscreen mode Exit fullscreen mode

Did you notice that what we just did would be equivalent to apply a not to our first example?

const isFive = (num) => num === 5
isFive(5) && console.log('It is the number five!') // it executes the console.log
!isFive(10) && console.log('It is not the number five!') // it executes the console.log
Enter fullscreen mode Exit fullscreen mode

Ternary operator

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark (?), then an expression to execute if the condition is truthy followed by a colon (:), and finally the expression to execute if the condition is falsy.

This is very commonly used to show different statuses or components to the user depending on a conditional statement. Though I don't always recommend to use the ternary operator, sometimes a good old fashion if does the job very well. It can be extremely useful for small things.

Take a look a the following example:

if (completed) {
    return 'Completed'
} else {
    return 'Pending'
}
Enter fullscreen mode Exit fullscreen mode

Another variation of that, which I still see around is:

if (completed) { return 'Completed'} else { return 'Pending' }
Enter fullscreen mode Exit fullscreen mode

I'm not here to judge, but that can get real messy. Let's take a look at a way using the ternary operator

return completed ? 'Completed' : 'Pending'
Enter fullscreen mode Exit fullscreen mode

Much nicer!

Optional Chaining

Last but not least, we have optional chaining (?.) that allows reading the value of a property located deep within a chain of connected objects without having to expressly validate each reference.

In plain English, it helps to avoid a bunch of if statements just to make sure we have a value on a nested property. Let's look at an example:

const juan = {
    name: 'Juan',
    marriedTo: {
        name: 'Diana'
    }
}

console.log(juan.marriedTo.name) // Diana
console.log(juan.divorcedFrom.name) // Cannot read property 'name' of undefined
Enter fullscreen mode Exit fullscreen mode

Ups.... when we tried to access the name of the person we are divorced from, we get an error, because divorcedFrom in our case is undefined. Normally we would solve it like this:

if (juan.divorcedFrom) {
    console.log(juan.divorcedFrom.name)
}
Enter fullscreen mode Exit fullscreen mode

But that can also get out of hands by adding a lot of ifs just for this purpose. There is a better way using optional chaining.

const juan = {
    name: 'Juan',
    marriedTo: {
        name: 'Diana'
    }
}

console.log(juan.marriedTo?.name) // Diana
console.log(juan.divorcedFrom?.name) // undefined
Enter fullscreen mode Exit fullscreen mode

And this can apply to multiple levels

juan.marriedTo?.disvorcedFrom?.kids
Enter fullscreen mode Exit fullscreen mode

Very nice! Let's move on with the next topic.


Spread Operator

There is no React app without making use of the spread operator, maybe that's exaggerated, but the spread operator is widely used in react applications, especially when working with reducers, though it is much more than just for that. This is another topic which I covered extensively in the article How to Use the Spread Operator (...) in JavaScript. I really recommend that you read it, it's pretty cool and covers the topic in detail.

The spread operator allows you to expand an iterable object into a list of its individual elements. Let's better take a look into some examples:

function sum(x, y, z) {
  return x + y + z
}

const numbers = [1, 2, 3]

console.log(sum(...numbers)) // 6
Enter fullscreen mode Exit fullscreen mode

In this case, what we are doing is to transform an array into separate variables that are passed to our sum function. It's a pretty neat trick. But we can also apply it for objects:

const obj1 = { foo: 'bar', x: 42 }
const obj2 = { foo: 'baz', y: 13 }

const copyObj1 = { ...obj1 } // This copies all the properties of obj1 into a new object.

const merged = { ...obj1, ...obj2 } // This merges all the properties of obj1 and obj2 into a new object.

console.log(merged) // {foo: "baz", x: 42, y: 13}
Enter fullscreen mode Exit fullscreen mode

Because we can use this to create new objects or arrays, its ideal to use with Redux, as we can avoid mutating the original objects.


Template Literals

Though very popular and beginners friendly, no list would be completed without them. Template literals are basically strings, but not any string, they allow embedded expressions. Let's take a look.

console.log(`this is a string literal`)
Enter fullscreen mode Exit fullscreen mode

In its more basic form, a string literal is just a string, however, note that for it to be a string literal it must use ` instead of " or '. It's a small detail but makes a huge difference.

String literals, for example, support multi-line strings:

console.log(`line 1
line 2`)
Enter fullscreen mode Exit fullscreen mode

Or you can also embed expressions

const a = 10
const b = 25

console.log(`a: ${a} and b: ${b} but more importantly a+b = ${a+b}`) // a: 10 and b: 25 but more importantly a+b = 35
Enter fullscreen mode Exit fullscreen mode

Really cool!


Conclusion

JavaScript is packed with useful operators, expressions and tricks to power up our development skills, and writer cleaner code. It is also true that some of the things I mention can be personal judgment, but if you look at the React code written on very popular projects you will see they apply these small things all over the place. So they are really good to learn and implement when you write your next React component.

Thanks for reading


If you like the story, please don't forget to subscribe to our free newsletter so we can stay connected: https://livecodestream.dev/subscribe

Top comments (1)

Collapse
 
pengeszikra profile image
Peter Vivo

Can shorter by object destructing in parameter list. Bonus Fragment: <> fix error

const TaskView({task:{title, description, completed}}) => (
  <>
    <h1>{title}</h1>
    <p>{description}</p>
    <span>{completed ? 'Completed' : 'Pending'}</span>
  </>
);