SonarQube 10.4 was recently released and, between 10.3 and 10.4, 48 new rules and one updated rule were released to help you to write clean code in your React applications.
Sonar was already serving React projects with a number of rules that Gabriel Vivas, product manager for JavaScript, described in the three-part Lesser-spotted React Mistakes blog series: Hooked on a Feeling, Zombie Methods, and What Are We Even Rendering?
This latest update to SonarQube focuses on three areas: avoiding deprecated methods, avoiding bad practices, and writing accessible applications. In this post, I will give an overview of what React developers can expect from SonarQube with this update and introduce a few of my favourite new rules.
If you want to try out these rules on your own codebase, install SonarLint in your editor (which is always free and uses the same analyser as SonarQube) and start using it while working on your React applications.
Deprecated methods
As progress with React marches on, the React team deprecate some old patterns and functions. Deprecated functions are replaced with better ways to achieve the same functionality and will eventually be removed, so you should gradually replace old uses and avoid writing any new code with them. Keeping up with React standards will ensure your code is consistent and easier to update to the latest React version.
For example, in class components, you can still use findDOMNode
to select the real DOM node for the instance. This has been deprecated in React's StrictMode since 2018, yet there are 133,000 files that reference findDOMNode
publicly on GitHub (some of those are implementations of the function, of course). As the official React documents say, Instead of using findDOMNode
, you should use a ref
.
The new rules that SonarQube will be enforcing to help you avoid deprecated methods are:
- Deprecated APIs should not be used (this existing rule was extended for React)
- React's
findDOMNode
should not be used - React's
isMounted
should not be used - String references should not be used
- React legacy lifecycle methods should not be used
Bad practices
In a fast-moving project, it's easy for inconsistencies or just plain mistakes to slip into your codebase. If you're lucky, you'll realise something's broken when you reload your application in the browser or run your tests. More typically, you have to debug when a bug is discovered in production. Having rules to check you are writing intentional code and avoiding these bad practices will save you time as you can fix them as soon as you discover them.
One thing I often find myself doing is using the wrong property names on DOM elements. I am always writing class
instead of className
, and I only discover it when my class name is not applied to the element I'm working with. The rule that JSX elements should not use unknown properties and attributes catches this, and SonarLint lets me know immediately that I've picked the wrong property name.
The full list of 16 new JavaScript rules to help us avoid these bad practices is:
- In React
this.state
should not be mutated directly - JSX elements should not use unknown properties and attributes
- React
children
should not be passed as prop - Redundant React fragments should be removed
- The return value of
ReactDOM.render
should not be used - The return value of
useState
should be destructured and named symmetrically setState
should use a callback when referencing the previous statethis
should not be used in functional componentschildren
anddangerouslySetInnerHTML
should not be used togethershouldComponentUpdate
should not be defined when extendingReact.PureComponent
- JSX special characters should be escaped
- Unused React typed props should be removed
- User-defined JSX components should use Pascal case
- Spacing between inline elements should be explicit
- React components should validate prop types
- All
defaultProps
should have non-required PropTypes
And there's one TypeScript-only rule that helps ensure that you can't mutate props in a child component, avoiding unpredictable behaviour.
Accessibility
Ensuring that your application is accessible is enormously important. Building an application that is accessible means that it allows everyone to fully use it, regardless of their abilities. In fact, accessible applications often benefit people without disabilities, too. For example, making sure apps are keyboard accessible helps those who can't use a mouse as well as those who just broke theirs. It is our responsibility to write code that will result in accessible applications.
Getting accessibility right can be difficult when building highly interactive applications, so any automation to help guide you is invaluable. This can be something like reminding you that elements that have mouse events should also respond to keyboard events or that you should implement buttons with the <button>
element and not a <div>
.
The complete list of new and updated rules to help you achieve accessible applications is below:
- Mouse events should have corresponding keyboard events
- ARIA properties in DOM elements should have valid values
- DOM elements with ARIA roles should have the required properties
- DOM elements with ARIA role should only have supported properties
- Prefer tag over ARIA role
- DOM elements with ARIA roles should have a valid non-abstract role
- No redundant ARIA role
- DOM elements with the
aria-activedescendant
property should be accessible via the tab key - No ARIA role or property for unsupported DOM elements
- Focusable elements should not have
aria-hidden
attribute - Anchors should contain accessible content
- Image, area, button with image, and object elements should have an alternative text
- DOM elements should use the
autocomplete
attribute correctly tabIndex
values should be 0 or -1- Non-interactive DOM elements should not have interactive ARIA roles
- Interactive DOM elements should not have non-interactive ARIA roles
- Anchor tags should not be used as buttons
- Non-interactive DOM elements should not have the
tabIndex
property - DOM elements should not use the
accesskey
property - Non-interactive elements shouldn't have event handlers
- Non-interactive DOM elements should not have an interactive handler
- HTML elements should have a valid language attribute
- Header elements should have accessible content
- Images should have a non-redundant alternate description
- Elements with an interactive role should support focus
- Label elements should have a text label and an associated control
- iFrames must have a title
- Media elements should have captions
It is impossible to catch all accessibility issues at the code level, though the above rules certainly help. You can also run tools like axe-core and Pa11y against your rendered application to help detect issues at runtime, as well as implement manual testing.
Clean Code in React
With this collection of new rules, SonarQube, SonarCloud and SonarLint are all set up to help you write consistent, intentional, adaptable and responsible code in your React applications. Check out all the other updates in the latest version of SonarQube 10.4 here.
If you're not already using SonarQube to scan your React projects, you can get started with the community edition or install SonarLint to see recommendations in your editor.