Skip to content

Commit

Permalink
Create rule S6790: Disallow using string references (`react/no-string…
Browse files Browse the repository at this point in the history
…-refs`) (#3187)
  • Loading branch information
github-actions[bot] authored Oct 11, 2023
1 parent 3ce9506 commit d908ea4
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
25 changes: 25 additions & 0 deletions rules/S6790/javascript/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"title": "String references should not be used",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"react"
],
"defaultSeverity": "Major",
"ruleSpecification": "RSPEC-6790",
"sqKey": "S6790",
"scope": "All",
"defaultQualityProfiles": ["Sonar way"],
"quickfix": "unknown",
"code": {
"impacts": {
"MAINTAINABILITY": "MEDIUM",
"RELIABILITY": "LOW"
},
"attribute": "CONVENTIONAL"
}
}
46 changes: 46 additions & 0 deletions rules/S6790/javascript/rule.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
== Why is this an issue?

React Refs provide a way to access DOM nodes or React elements created in the render method.

Older React versions allowed the ref attribute to be a string, like `"textInput"`, later accessible as `this.refs.textInput`. This is considered legacy code due to multiple reasons:

* String `refs` make React slower as they force React to keep track of what component is currently executing.
* String `refs` are not composable: if a library puts a ref on the passed child, the user can't put another ref on it.
* The owner of a string `ref` is determined by the currently executing component.
[source,javascript,diff-id=1,diff-type=noncompliant]
----
const Hello = createReactClass({
componentDidMount: function() {
const component = this.refs.hello; // Noncompliant
// ...
},
render: function() {
return <div ref="hello">Hello, world.</div>;
}
});
----

Instead, reference callbacks should be used. These do not have the limitations mentioned above. When the DOM node is added to the screen, React will call the `ref` callback with the DOM node as the argument. When that DOM node is removed, React will call your `ref` callback with `null`. One should return `undefined` from the `ref` callback.

[source,javascript,diff-id=1,diff-type=compliant]
----
const Hello = createReactClass({
componentDidMount: function() {
const component = this.hello;
// ...
},
render() {
return <div ref={(c) => { this.hello = c; }}>Hello, world.</div>;
}
});
----

== Resources
=== Documentation

* https://react.dev/reference/react-dom/components/common#ref-callback[React - `ref` callback function]
* https://legacy.reactjs.org/docs/refs-and-the-dom.html[React - Refs and the DOM]
* https://react.dev/learn/manipulating-the-dom-with-refs[React - Manipulating the DOM with Refs]
* https://react.dev/reference/react/useRef[React - `useRef`]
* https://react.dev/reference/react/createRef#createref[React - `createRef`]
2 changes: 2 additions & 0 deletions rules/S6790/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}

0 comments on commit d908ea4

Please sign in to comment.