This series is dedicated to the small, but common pitfalls and errors you can encounter when writing React code. Whether an experienced JavaScript | TypeScript developer or just starting out, the results can be surprising.
These are the kind of issues you want to catch early in your IDE before you spend hours debugging. You can copy/paste the code examples in VS Code with the SonarLint plugin if you want to see them for yourself and try to catch them before they happen to you!
Render what?
In this third and final installment of the series, we’ll look at three subtle defects that go from rendering unexpected characters, to silently not rendering anything at all.
These insidious mistakes are small in character count, but produce real problems that are hard to track once they find their way into your codebase 😈.
Render non-boolean values
When using JSX in React you can conditionally render your components. One common way to do it is using the logical AND operator &&
to render when there is a truthy value or show nothing in the other case.
Here’s an example Component that greets people when necessary, let’s call it Greeting.tsx
since it uses TypeScript:
If you are following along at home in VS Code, make sure you have a tsconfig.json
too:
Alternatively, if you’re into terminals and you already have the npm
command, you can run:
Well done! You’ve got yourself some over-engineered greeting with optional rendering. Nice.
However, this pattern does not always work as expected. We managed to introduce a bug already. Look at this other example of a Component that simply shows a list of names. Try to spot the issue:
Surprisingly, when people
is an empty Array this will render “0”
instead of nothing 🤯.
Since the number zero is a falsy value there would be no list to show. However, React treats the number 0
as a legitimate value to render as a String. More generally, React will render all non-boolean falsy value types, like Number or BigInt. This includes NaN
, which might also come from an arithmetic issue.
Furthermore, if you are using React Native, your render method will actually crash with 0
or NaN
values 💥.
To be safe, you can use a ternary to explicitly return null
if that is what you intended:
You could also write an expression that evaluates to a real boolean, like so:
Now, how to detect this issue before it creates an obscure bug?
Unfortunately, because this is related to how React components work, JavaScript thinks this is what you want. Not even TypeScript could detect an issue.
Of course, if you’re using SonarLint, you’re covered 😎. See below:
In case you’re wondering, Eslint also has a rule for detecting this. Although you might need to add the eslint-plugin-react
plugin and configure it in your .eslintrc.json
file. Note that this rule is NOT included by default in the React plugin’s “react/recommended” setting, you need to add it manually even if you are already extending:
Render your comments
Not all comments are made alike. As you know, there are a few ways to create comments in JavaScript and TypeScript:
That’s all fine. The problem comes when you try to do that within JSX in a React Component. Can you guess what this will render?
More than a div
. It turns out it will render the string // nothing here too
😅. This will also happen if you use the multiline comment syntax:
Besides the div
, that will render the string /* nothing here */
🙃. But why?
What we are commonly using in React Components is JSX, not HTML or XML, even if it looks similar. Being a syntax extension, it needs some preprocessing to be converted into valid ECMAScript code.
It can help to see what the plain JavaScript version of the JSX would look like. It’s just a function call:
If you know your HTML or XML, you might dare to try this version:
Which will actually crash your component with a SyntaxError
caused by an unexpected token, the exclamation mark 💥.
How are you supposed to add comments in JSX? Well, you’ll need to use curly braces { }
to tell JSX that you are embedding a JavaScript expression and not a regular String:
As with the first pitfall we shared, TypeScript won’t help us since it has no way to know if we really want the string // nothing here
.
SonarLint has your back once again here. Both single-line and multi-line comments will be detected as bugs as you write them in VS Code or your IDE of choice 👍.
Eslint has a “recommended” rule for this one. You will need to add the eslint-plugin-react
plugin and explicitly extend it in your .eslintrc.json
file:
Render a lot of nothing
This is a silly one that can make you pull your hair out 🧑🦲.
As we code all day, we can become blind to subtle details. The real problem comes when there is no issue raised by our tools, in this case TypeScript or React.
Try to find the problem with this small component:
Did you see that one? Or more precisely, did not see the missing return
statement?
React will happily render a lot of nothing, without any errors, and leave you alone to figure it out.
This can happen easily if you are using regular parenthesis where no return
is needed, and maybe mixed up with curly braces.
This is how that should look if you wanted to render something:
Maybe hard to catch if you look too quickly 👀. It could be in the newspaper or in a puzzle book.
Anyway, using parenthesis means now we are implicitly returning a single JSX expression. That works as expected.
You could also be more explicit with the return statement while keeping the curly braces:
As expected, SonarLint will help you while you’re writing the code. It will raise an issue since this is very likely an annoying bug 🐛.
In this case, there is no Eslint rule available. There is react/require-render-return
that can help detect missing return
statements in React Classes. Unfortunately, it won't work for functional components like the ones in our examples. Nevertheless, it comes with “react/recommended” and it is better than nothing!
Prevent issues before they happen
As you see, there can be some non-obvious edge cases when rendering components in React.
Some of these cases can be detected with Eslint, although you might need some setup as described in each case. Others are more subtle.
By default, SonarLint will detect all these issues and warn you as they come up, so you can fix them on the spot, without losing focus, allowing you to write clean code. If you want to dig deeper, SonarLint will also provide an explanation as to why they happen in the first place🧐. Sort of what we did in this article.
That’s a wrap
Thank you for following this blog series about React and SonarLint, it's been fun! We are already preparing our next series about JavaScript and SonarLint, designed to help you Clean as You Code. See you in a whale 🐋!
If you liked this post, send us a Tweet @SonarSource or a comment in the Community. We’d love to hear about your experience.
Read more about these rules in our catalog:
- S6439 React components should not render non-boolean condition values
- S6438 Comments inside JSX expressions should be enclosed in curly braces
- S6435 React render function should return a value
[Previous posts]