Skip to content

Commit a1faa7e

Browse files
committed
Add LEGACY.md
1 parent 24cb0be commit a1faa7e

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed

LEGACY.md

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
## Legacy `react-codemod`
2+
3+
All codemods in this repo can be run using the legacy `react-codemod` command, which runs the codemods via jscodeshift directly.
4+
5+
### Usage
6+
7+
We recommend using the [`codemod`](github.com/reactjs/react-codemod) command for improved experience and support.
8+
9+
To use `react-codemod` directly:
10+
11+
`npx react-codemod <transform> <path> [...options]`
12+
* `transform` - name of transform, see available transforms below.
13+
* `path` - files or directory to transform
14+
* use the `--dry` option for a dry-run and use `--print` to print the output for comparison
15+
16+
This will start an interactive wizard, and then run the specified transform.
17+
18+
### Included Transforms
19+
20+
#### `remove-context-provider`
21+
22+
Converts `Context.Provider` JSX opening and closing elements into `Context`.
23+
24+
```sh
25+
npx react-codemod remove-context-provider <path>
26+
```
27+
28+
#### `remove-forward-ref`
29+
30+
Removes usages of `forwardRef`.
31+
32+
```sh
33+
npx react-codemod remove-forward-ref <path>
34+
```
35+
36+
#### `use-context-hook`
37+
38+
```sh
39+
npx react-codemod use-context-hook <path>
40+
```
41+
42+
#### `replace-act-import`
43+
44+
```sh
45+
npx react-codemod replace-act-import <path>
46+
```
47+
48+
#### `replace-string-ref`
49+
50+
Replaces deprecated string refs with callback refs.
51+
52+
```sh
53+
npx react-codemod replace-string-ref <path>
54+
```
55+
56+
#### `replace-use-form-state`
57+
58+
Replaces usages of useFormState() to use useActionState().
59+
60+
```sh
61+
npx react-codemod replace-use-form-state <path>
62+
```
63+
64+
#### `replace-reactdom-render`
65+
66+
Replaces usages of ReactDom.render() with createRoot(node).render().
67+
68+
```sh
69+
npx react-codemod replace-reactdom-render <path>
70+
```
71+
72+
#### `create-element-to-jsx`
73+
74+
Converts calls to `React.createElement` into JSX elements.
75+
76+
```sh
77+
npx react-codemod create-element-to-jsx <path>
78+
```
79+
80+
#### `error-boundaries`
81+
82+
Renames the experimental `unstable_handleError` lifecycle hook to `componentDidCatch`.
83+
84+
```sh
85+
npx react-codemod error-boundaries <path>
86+
```
87+
88+
#### `findDOMNode`
89+
90+
Updates `this.getDOMNode()` or `this.refs.foo.getDOMNode()` calls inside of
91+
`React.createClass` components to `React.findDOMNode(foo)`. Note that it will
92+
only look at code inside of `React.createClass` calls and only update calls on
93+
the component instance or its refs. You can use this script to update most calls
94+
to `getDOMNode` and then manually go through the remaining calls.
95+
96+
```sh
97+
npx react-codemod findDOMNode <path>
98+
```
99+
100+
#### `manual-bind-to-arrow`
101+
102+
Converts manual function bindings in a class (e.g., `this.f = this.f.bind(this)`) to arrow property initializer functions (e.g., `f = () => {}`).
103+
104+
```sh
105+
npx react-codemod manual-bind-to-arrow <path>
106+
```
107+
108+
#### `pure-component`
109+
110+
Converts ES6 classes that only have a render method, only have safe properties
111+
(statics and props), and do not have refs to Functional Components.
112+
113+
The wizard will ask for 2 options -
114+
115+
* **Use arrow functions?**: converts to arrow function. Converts to `function` by default.
116+
* **Destructure props?**: will destructure props in the argument where it is safe to do so.
117+
118+
```sh
119+
npx react-codemod pure-component <path>
120+
```
121+
122+
#### `pure-render-mixin`
123+
124+
Removes `PureRenderMixin` and inlines `shouldComponentUpdate` so that the ES2015
125+
class transform can pick up the React component and turn it into an ES2015
126+
class. NOTE: This currently only works if you are using the master version
127+
(>0.13.1) of React as it is using `React.addons.shallowCompare`
128+
129+
```sh
130+
npx react-codemod pure-render-mixin <path>
131+
```
132+
133+
* The wizard will ask to optionally override `mixin-name`, and look for it
134+
instead of `PureRenderMixin`. Note that it is not possible to use a
135+
namespaced name for the mixin. `mixins: [React.addons.PureRenderMixin]` will
136+
not currently work.
137+
138+
#### `React-PropTypes-to-prop-types`
139+
140+
Replaces `React.PropTypes` references with `prop-types` and adds the appropriate `import` or `require` statement. This codemod is intended for React 15.5+.
141+
142+
```sh
143+
npx react-codemod React-PropTypes-to-prop-types <path>
144+
```
145+
146+
* In addition to running the above codemod you will also need to install the `prop-types` NPM package.
147+
148+
#### `rename-unsafe-lifecycles`
149+
150+
Adds `UNSAFE_` prefix for deprecated lifecycle hooks. (For more information about this codemod, see [React RFC #6](https://github.com/reactjs/rfcs/pull/6))
151+
152+
```sh
153+
npx react-codemod rename-unsafe-lifecycles <path>
154+
```
155+
156+
#### `react-to-react-dom`
157+
158+
Updates code for the split of the `react` and `react-dom` packages (e.g.,
159+
`React.render` to `ReactDOM.render`). It looks for `require('react')` and
160+
replaces the appropriate property accesses using `require('react-dom')`. It does
161+
not support ES6 modules or other non-CommonJS systems. We recommend performing
162+
the `findDOMNode` conversion first.
163+
164+
165+
```sh
166+
npx react-codemod react-to-react-dom <path>
167+
```
168+
169+
* After running the automated codemod, you may want to run a regex-based
170+
find-and-replace to remove extra whitespace between the added requires, such
171+
as `codemod.py -m -d src --extensions js '(var
172+
React\s*=\s*require\(.react.\);)\n\n(\s*var ReactDOM)' '\1\n\2'` using
173+
https://github.com/facebook/codemod.
174+
175+
#### `React-DOM-to-react-dom-factories`
176+
177+
Converts calls like `React.DOM.div(...)` to `React.createElement('div', ...)`.
178+
179+
```sh
180+
npx react-codemod React-DOM-to-react-dom-factories <path>
181+
```
182+
183+
#### `ReactNative-View-propTypes`
184+
185+
Replaces `View.propTypes` references with `ViewPropTypes` and adds the appropriate `import` or `require` statement. This codemod is intended for ReactNative 44+.
186+
187+
```sh
188+
npx react-codemod ReactNative-View-propTypes <path>
189+
```
190+
191+
#### `sort-comp`
192+
193+
Reorders React component methods to match the [ESLint](http://eslint.org/)
194+
[react/sort-comp
195+
rule](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md). (Defaults to ordering of the [Airbnb style
196+
guide](https://github.com/airbnb/javascript/blob/7684892951ef663e1c4e62ad57d662e9b2748b9e/packages/eslint-config-airbnb/rules/react.js#L122-L134).
197+
198+
`react-codemod`:
199+
```sh
200+
npx react-codemod sort-comp <path>
201+
```
202+
203+
#### `update-react-imports`
204+
205+
[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'`).
206+
207+
The wizard will ask for 1 option -
208+
209+
* **Destructure namespace imports as well?**: If chosen, *namespace* imports like `import * as React` will *also* be converted. By default, it's false, so only default imports (`import React`) are converted.
210+
211+
```sh
212+
npx react-codemod update-react-imports <path>
213+
```
214+
215+
### Explanation of the new ES2015 class transform with property initializers
216+
1. Determine if mixins are convertible. We only transform a `createClass` call to an ES6 class component when:
217+
- There are no mixins on the class, or
218+
- `options['pure-component']` is true, the `mixins` property is an array and it _only_ contains pure render mixin (the specific module name can be specified using `options['mixin-module-name']`, which defaults to `react-addons-pure-render-mixin`)
219+
2. Ignore components that:
220+
- Call deprecated APIs. This is very defensive, if the script finds any identifiers called `isMounted`, `getDOMNode`, `replaceProps`, `replaceState` or `setProps` it will skip the component
221+
- Explicitly call `this.getInitialState()` and/or `this.getDefaultProps()` since an ES6 class component will no longer have these methods
222+
- Use `arguments` in methods since arrow functions don't have `arguments`. Also please notice that `arguments` should be [very carefully used](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments) and it's generally better to switch to spread (`...args`) instead
223+
- Have inconvertible `getInitialState()`. Specifically if you have variable declarations like `var props = ...` and the right hand side is not `this.props` then we can't inline the state initialization in the `constructor` due to variable shadowing issues
224+
- Have non-primitive right hand side values (like `foo: getStuff()`) in the class spec
225+
3. Transform it to an ES6 class component
226+
1. Replace `var A = React.createClass(spec)` with `class A extends React.Component {spec}`. If a component uses pure render mixin and passes the mixins test (as described above), it will extend `React.PureComponent` instead
227+
- Remove the `require`/`import` statement that imports pure render mixin when it's no longer being referenced
228+
2. Pull out all statics defined on `statics` plus the few special cased statics like `childContextTypes`, `contextTypes`, `displayName`, `getDefaultProps()`, and `propTypes` and transform them to `static` properties (`static propTypes = {...};`)
229+
- If `getDefaultProps()` is simple (i.e. it only contains a return statement that returns something) it will be converted to a simple assignment (`static defaultProps = ...;`). Otherwise an IIFE (immediately-invoked function expression) will be created (`static defaultProps = function() { ... }();`). Note that this means that the function will be executed only a single time per app-lifetime. In practice this hasn't caused any issues — `getDefaultProps` should not contain any side-effects
230+
3. Transform `getInitialState()`
231+
- If there's no `getInitialState()` or the `getInitialState()` function is simple (i.e., it only contains a return statement that returns something) then we don't need a constructor; `state` will be lifted to a property initializer (`state = ...;`)
232+
- However, if the RHS of `return` contains references to `this` other than `this.props` and/or `this.context`, we can't be sure about what you'll need from `this`. We need to ensure that our property initializers' evaluation order is safe, so we defer `state`'s initialization by moving it all the way down until all other property initializers have been initialized
233+
- If `getInitialState()` is not simple, we create a `constructor` and convert `getInitialState()` to an assignment to `this.state`
234+
- `constructor` always have `props` as the first parameter
235+
- We only put `context` as the second parameter when (one of) the following things happen in `getInitialState()`:
236+
- It accesses `this.context`, or
237+
- There's a direct method call `this.x()`, or
238+
- `this` is referenced alone
239+
- Rewrite accesses to `this.props` to `props` and accesses to `this.context` to `context` since the values will be passed as `constructor` arguments
240+
- Remove _simple_ variable declarations like `var props = this.props;` and `var context = this.context`
241+
- Rewrite top-level return statements (`return {...};`) to `this.state = {...}`
242+
- Add `return;` after the assignment when the return statement is part of a control flow statement (not a direct child of `getInitialState()`'s body) and not in an inner function declaration
243+
4. Transform all non-lifecycle methods and fields to class property initializers (like `onClick = () => {};`). All your Flow annotations will be preserved
244+
- It's actually not necessary to transform all methods to arrow functions (i.e., to bind them), but this behavior is the same as `createClass()` and we can make sure that we won't accidentally break stuff
245+
4. Generate Flow annotations from `propTypes` and put it on the class (this only happens when there's `/* @flow */` in your code and `options['flow']` is `true`)
246+
- Flow actually understands `propTypes` in `createClass` calls but not ES6 class components. Here the transformation logic is identical to [how](https://github.com/facebook/flow/blob/master/src/typing/statement.ml#L3526) Flow treats `propTypes`
247+
- Notice that Flow treats an optional propType as non-nullable
248+
- For example, `foo: React.PropTypes.number` is valid when you pass `{}`, `{foo: null}`, or `{foo: undefined}` as props at **runtime**. However, when Flow infers type from a `createClass` call, only `{}` and `{foo: undefined}` are valid; `{foo: null}` is not. Thus the equivalent type annotation in Flow is actually `{foo?: number}`. The question mark on the left hand side indicates `{}` and `{foo: undefined}` are fine, but when `foo` is present it must be a `number`
249+
- For `propTypes` fields that can't be recognized by Flow, `$FlowFixMe` will be used
250+
5. `React.createClass` is no longer present in React 16. So, if a `createClass` call cannot be converted to a plain class, the script will fallback to using the `create-react-class` package.
251+
- Replaces `React.createClass` with `ReactCreateClass`.
252+
- Adds a `require` or `import` statement for `create-react-class`. The import style is inferred from the import style of the `react` import. The default module name can be overridden with the `--create-class-module-name` option.
253+
- Prunes the `react` import if there are no more references to it.
254+
255+
256+
## `react-codemod` options
257+
258+
### jscodeshift options
259+
260+
To pass more options directly to jscodeshift, use `--jscodeshift="..."`. For example:
261+
```sh
262+
npx react-codemod --jscodeshift="--run-in-band --verbose=2"
263+
```
264+
265+
See all available options [here](https://github.com/facebook/jscodeshift#usage-cli).
266+
267+
### Recast Options
268+
269+
Options to [recast](https://github.com/benjamn/recast)'s printer can be provided
270+
through jscodeshift's `printOptions` command line argument
271+
272+
```sh
273+
npx react-codemod <transform> <path> --jscodeshift="--printOptions='{\"quote\":\"double\"}'"
274+
```
275+
276+
### `explicit-require=false`
277+
278+
If you're not explicitly importing React in your files (eg: if you're loading React with a script tag), you should add `--explicit-require=false`.
279+

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