Hey, long time no see 👋🏾!
I haven't written anything in a long while so I'm trying to eaaase back into it. Just like riding a bike, eh?
I've been at my new job for about 7 months now and every day I encounter new challenges that have me racking my brain for hours, days and sometimes weeks. It's not just about solving the coding problem. It's also about maintaining code consistency, readability, making sure you follow best practices, keeping it simple etc. You have to find the right balance between all of those things.
So, I thought it would be a good idea to start documenting the challenges, big and small, right here on dev.to to not only help me document things that have tripped me up in the past (or present), but also to create discussion about best practices and ways to improve. I hope that by doing this, I can learn and grow as a developer and help others in the process, too. You can never have too much documentation!
ESLint warnings
Earlier this week, I encountered two ESLint warnings, one after the other. The warning were:
- no nested ternary
- no mixed operators
ESLint forbids the use of nested ternary operators and once I looked into the documentation, it stated that this was due to readability - nested ternary operators make the code more difficult to understand. The reasoning behind the "no mixed operators" rule relates to readability, as well.
Now, that is not to say that nested ternary operators and mixed operators don't work - they do. However, just because it works does not mean it should be used. So, if nested ternary operators and mixed operators are a no-no, what can we do instead?
Let's have a look at the code:
import React from 'react';
const Example = props => (
<div className="wrapper">
{props.apples && props.bananas || props.apples && !props.bananas
? (
<div>
{props.apples.map(apple => (
<div>{apple.color}</div>
))
}
</div>
)
:
props.bananas && !props.apples
? (
<div>
{props.bananas.map(banana => (
<div>{banana.color}</div>
))
}
</div>
)
:
''
}
</div>
)
export default Example;
Here, we are trying to conditionally render two components, depending on what statements are true. If both apples and bananas exist OR if only apples exists, we want to render apples.color, otherwise if bananas exist but apples does not exist, we want to render bananas.color and in all other cases, we want to render an empty string.
Like we mentioned before, this code triggers two ESLint warnings, one that relates to the use of nested ternary operators and the other warning relates to the use of mixed operators "&&" and "||".
First thing we can do here to improve readability is to store the statements in consts. One const to represent the statement where both apple and bananas exist, another to represent the statement where only apples exist and another to represent the statement where only bananas exist.
In order to use our consts and have access to our props, we must turn our const Example into a function statement. Our code will now look like this:
import React from 'react';
const Example = props => {
const onlyApples = props.apples && !props.bananas;
const onlyBananas = props.bananas && !props.apples;
const applesAndBananas = props.apples & props.bananas;
<div className="wrapper">
{applesAndBananas || onlyApples
? (
<div>
{props.apples.map(apple => (
<div>{apple.color}</div>
))
}
</div>
)
:
onlyBananas
? (
<div>
{props.bananas.map(banana => (
<div>{banana.color}</div>
))
}
</div>
)
:
''
}
</div>
}
export default Example;
By storing our statements in consts, it has already made the code more readable. This has also cleared the ESLint warning that relates to the use of mixed operators "&&" and "||". Now, to deal with the "no-nested ternary" warning.
To deal with this ESLint warning, I decided to split the nested ternary operator into two blocks and use two conditional rendering techniques instead: the traditional ternary operator and logical && operator.
I used the ternary operator to deal with the top half of the nested ternary operator (i.e. when both apples and bananas are true OR when only apples is true), and used the logical && operator to deal with the statement that deals with onlyBananas.
At the end, the code looked like this:
import React from 'react';
const Example = props => {
const onlyApples = props.apples && !props.bananas;
const onlyBananas = props.bananas && !props.apples;
const applesAndBananas = props.apples & props.bananas;
<div className="wrapper">
{onlyBananas
&& (
<div>
{props.bananas.map(banana => (
<div>{banana.color}</div>
))
}
</div>
)
}
{applesAndBananas || onlyApples
? (
<div>
{props.apples.map(apple => (
<div>{apple.color}</div>
))
}
</div>
)
:
''
}
</div>
}
export default Example;
For those who are not familiar with logical && operators, and using the code above as an example - when onlyBananas is true, it will render bananas.color, and if it isn't true, it will render nothing.
The ternary operator will deal with the other part from the nested ternary operator. If applesAndBananas is true OR if onlyApples is true, it will render apples.color, otherwise it will render an empty string.
Recommended resources/documentation:
- All React Conditional Rendering Techniques by ROBIN WIERUCH
- Disallow mixes of different operators
- Disallow nested ternary expressions
If you got this far, I hope you enjoyed reading this post! Of course, this is not the only one way of tackling this specific problem - this is one way of doing so. I'd love to hear any input on how you would tackle this, and if there are even better ways to do so! 🙂
*As a general rule, I will not be sharing the actual code used as it is private, thus will be using example code instead to illustrate the problem.