Skip to content

Commit 63feb87

Browse files
committed
feat: Add codemod to transform string refs to arrow-functions
1 parent 243edf6 commit 63feb87

12 files changed

+299
-0
lines changed

README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,76 @@ guide](https://github.com/airbnb/javascript/blob/7684892951ef663e1c4e62ad57d662e
143143
npx react-codemod sort-comp <path>
144144
```
145145

146+
#### `string-refs`
147+
148+
WARNING: Only apply this codemod if you've fixed all warnings like this:
149+
150+
```
151+
Warning: Component "div" contains the string ref "inner". Support for string refs will be removed in a future major release. We recommend using useRef() or createRef() instead.
152+
```
153+
154+
This codemod will convert deprecated string refs to callback refs.
155+
156+
Input:
157+
158+
```jsx
159+
import * as React from "react";
160+
161+
class ParentComponent extends React.Component {
162+
render() {
163+
return <div ref="refComponent" />;
164+
}
165+
}
166+
```
167+
168+
Output:
169+
170+
```jsx
171+
import * as React from "react";
172+
173+
class ParentComponent extends React.Component {
174+
render() {
175+
return (
176+
<div
177+
ref={(current) => {
178+
this.refs["refComponent"] = current;
179+
}}
180+
/>
181+
);
182+
}
183+
}
184+
```
185+
186+
Note that this only works for string literals.
187+
Referring to the ref with a variable will not trigger the transform:
188+
Input:
189+
190+
```jsx
191+
import * as React from "react";
192+
193+
const refName = "refComponent";
194+
195+
class ParentComponent extends React.Component {
196+
render() {
197+
return <div ref={refName} />;
198+
}
199+
}
200+
```
201+
202+
Output (nothing changed):
203+
204+
```jsx
205+
import * as React from "react";
206+
207+
const refName = "refComponent";
208+
209+
class ParentComponent extends React.Component {
210+
render() {
211+
return <div ref={refName} />;
212+
}
213+
}
214+
```
215+
146216
#### `update-react-imports`
147217

148218
[As of Babel 7.9.0](https://babeljs.io/blog/2020/03/16/7.9.0#a-new-jsx-transform-11154-https-githubcom-babel-babel-pull-11154), when using `runtime: automatic` in `@babel/preset-react` or `@babel/plugin-transform-react-jsx`, you will not need to explicitly import React for compiling jsx. This codemod removes the redundant import statements. It also converts default imports (`import React from 'react'`) to named imports (e.g. `import { useState } from 'react'`).

bin/cli.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ const TRANSFORMER_INQUIRER_CHOICES = [
188188
'Reorders React component methods to match the ESLint react/sort-comp rule.',
189189
value: 'sort-comp'
190190
},
191+
{
192+
name:
193+
'string-refs: Converts deprecated string refs to callback refs.',
194+
value: 'string-refs'
195+
},
191196
{
192197
name: 'update-react-imports: Removes redundant import statements from explicitly importing React to compile JSX and converts default imports to destructured named imports',
193198
value: 'update-react-imports',
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as React from "react";
2+
3+
class ParentComponent extends React.Component {
4+
render() {
5+
return (
6+
<div ref="P" id="P">
7+
<div ref="P_P1" id="P_P1">
8+
<span ref="P_P1_C1" id="P_P1_C1" />
9+
<span ref="P_P1_C2" id="P_P1_C2" />
10+
</div>
11+
<div ref="P_OneOff" id="P_OneOff" />
12+
</div>
13+
);
14+
}
15+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as React from "react";
2+
3+
class ParentComponent extends React.Component {
4+
render() {
5+
return (
6+
<div ref={current => {
7+
this.refs['P'] = current;
8+
}} id="P">
9+
<div ref={current => {
10+
this.refs['P_P1'] = current;
11+
}} id="P_P1">
12+
<span ref={current => {
13+
this.refs['P_P1_C1'] = current;
14+
}} id="P_P1_C1" />
15+
<span ref={current => {
16+
this.refs['P_P1_C2'] = current;
17+
}} id="P_P1_C2" />
18+
</div>
19+
<div ref={current => {
20+
this.refs['P_OneOff'] = current;
21+
}} id="P_OneOff" />
22+
</div>
23+
);
24+
}
25+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import * as React from "react";
2+
3+
<div ref="bad" />;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import * as React from "react";
2+
3+
<div ref={current => {
4+
this.refs['bad'] = current;
5+
}} />;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from "react";
2+
3+
class ParentComponent extends React.Component {
4+
// Actual code probably has more accurate types.
5+
// Codemod might cause TypeScript errors but these are good errors since they reveal unsound code.
6+
refs: Record<string, any>;
7+
8+
render() {
9+
return (
10+
<div ref="P" id="P">
11+
<div ref="P_P1" id="P_P1">
12+
<span ref="P_P1_C1" id="P_P1_C1" />
13+
<span ref="P_P1_C2" id="P_P1_C2" />
14+
</div>
15+
<div ref="P_OneOff" id="P_OneOff" />
16+
</div>
17+
);
18+
}
19+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import * as React from "react";
2+
3+
class ParentComponent extends React.Component {
4+
// Actual code probably has more accurate types.
5+
// Codemod might cause TypeScript errors but these are good errors since they reveal unsound code.
6+
refs: Record<string, any>;
7+
8+
render() {
9+
return (
10+
<div ref={current => {
11+
this.refs['P'] = current;
12+
}} id="P">
13+
<div ref={current => {
14+
this.refs['P_P1'] = current;
15+
}} id="P_P1">
16+
<span ref={current => {
17+
this.refs['P_P1_C1'] = current;
18+
}} id="P_P1_C1" />
19+
<span ref={current => {
20+
this.refs['P_P1_C2'] = current;
21+
}} id="P_P1_C2" />
22+
</div>
23+
<div ref={current => {
24+
this.refs['P_OneOff'] = current;
25+
}} id="P_OneOff" />
26+
</div>
27+
);
28+
}
29+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as React from "react";
2+
3+
class ParentComponent extends React.Component {
4+
render() {
5+
const refName = "P";
6+
// Giving up. Would need to implement scope tracking.
7+
return <div ref={refName} id="P"></div>;
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as React from "react";
2+
3+
class ParentComponent extends React.Component {
4+
render() {
5+
const refName = "P";
6+
// Giving up. Would need to implement scope tracking.
7+
return <div ref={refName} id="P"></div>;
8+
}
9+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy