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!
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
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:
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
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?
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
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:
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.
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
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
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
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
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