Skip to content

Commit fe93797

Browse files
Align no-deprecated rule with React 18 deprecations
1 parent adebc71 commit fe93797

File tree

3 files changed

+160
-4
lines changed

3 files changed

+160
-4
lines changed

docs/rules/no-deprecated.md

+22-2
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,24 @@ import React, { PropTypes } from 'react';
3636
componentWillMount() { }
3737
componentWillReceiveProps() { }
3838
componentWillUpdate() { }
39+
40+
// React 18 deprecations
41+
import { render } from 'react-dom';
42+
ReactDOM.render(<div></div>, container);
43+
44+
import { hydrate } from 'react-dom';
45+
ReactDOM.hydrate(<div></div>, container);
46+
47+
import {unmountComponentAtNode} from 'react-dom';
48+
ReactDOM.unmountComponentAtNode(container);
49+
50+
import { renderToNodeStream } from 'react-dom/server';
51+
ReactDOMServer.renderToNodeStream(element);
3952
```
4053

4154
Examples of **correct** code for this rule:
4255

4356
```jsx
44-
ReactDOM.render(<MyComponent />, root);
45-
4657
// When [1, {"react": "0.13.0"}]
4758
ReactDOM.findDOMNode(this.refs.foo);
4859

@@ -51,4 +62,13 @@ import { PropTypes } from 'prop-types';
5162
UNSAFE_componentWillMount() { }
5263
UNSAFE_componentWillReceiveProps() { }
5364
UNSAFE_componentWillUpdate() { }
65+
66+
ReactDOM.createPortal(child, container);
67+
68+
import { createRoot } from 'react-dom/client';
69+
const root = createRoot(container);
70+
root.unmount();
71+
72+
import { hydrateRoot } from 'react-dom/client';
73+
const root = hydrateRoot(container, <App/>);
5474
```

lib/rules/no-deprecated.js

+25
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ const report = require('../util/report');
2222
const MODULES = {
2323
react: ['React'],
2424
'react-addons-perf': ['ReactPerf', 'Perf'],
25+
'react-dom': ['ReactDOM'],
26+
'react-dom/server': ['ReactDOMServer'],
2527
};
2628

2729
// ------------------------------------------------------------------------------
@@ -82,6 +84,29 @@ function getDeprecated(pragma) {
8284
'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
8385
+ 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
8486
];
87+
// 18.0.0
88+
// https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#deprecations
89+
deprecated['ReactDOM.render'] = [
90+
'18.0.0',
91+
'createRoot',
92+
'https://reactjs.org/link/switch-to-createroot',
93+
];
94+
deprecated['ReactDOM.hydrate'] = [
95+
'18.0.0',
96+
'hydrateRoot',
97+
'https://reactjs.org/link/switch-to-createroot',
98+
];
99+
deprecated['ReactDOM.unmountComponentAtNode'] = [
100+
'18.0.0',
101+
'root.unmount',
102+
'https://reactjs.org/link/switch-to-createroot',
103+
];
104+
deprecated['ReactDOMServer.renderToNodeStream'] = [
105+
'18.0.0',
106+
'renderToPipeableStream',
107+
'https://reactjs.org/docs/react-dom-server.html#rendertonodestream',
108+
];
109+
85110
return deprecated;
86111
}
87112

tests/lib/rules/no-deprecated.js

+113-2
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ ruleTester.run('no-deprecated', rule, {
4848
// Not deprecated
4949
'var element = React.createElement(\'p\', {}, null);',
5050
'var clone = React.cloneElement(element);',
51-
'ReactDOM.render(element, container);',
52-
'ReactDOM.unmountComponentAtNode(container);',
51+
'ReactDOM.cloneElement(child, container);',
5352
'ReactDOM.findDOMNode(instance);',
53+
'ReactDOM.createPortal(child, container);',
5454
'ReactDOMServer.renderToString(element);',
5555
'ReactDOMServer.renderToStaticMarkup(element);',
5656
{
@@ -119,6 +119,29 @@ ruleTester.run('no-deprecated', rule, {
119119
let { default: defaultReactExport, ...allReactExports } = React;
120120
`,
121121
},
122+
// React 18 API
123+
{
124+
code: `
125+
import ReactDOM, { createRoot } from 'react-dom/client';
126+
ReactDOM.createRoot(container);
127+
const root = createRoot(container);
128+
root.unmount();
129+
`,
130+
},
131+
{
132+
code: `
133+
import ReactDOM, { hydrateRoot } from 'react-dom/client';
134+
ReactDOM.hydrateRoot(container, <App/>);
135+
hydrateRoot(container, <App/>);
136+
`,
137+
},
138+
{
139+
code: `
140+
import ReactDOMServer, { renderToPipeableStream } from 'react-dom/server';
141+
ReactDOMServer.renderToPipeableStream(<App />, {});
142+
renderToPipeableStream(<App />, {});
143+
`,
144+
},
122145
]),
123146

124147
invalid: parsers.all([
@@ -454,5 +477,93 @@ ruleTester.run('no-deprecated', rule, {
454477
),
455478
],
456479
},
480+
{
481+
code: `
482+
import { render } from 'react-dom';
483+
ReactDOM.render(<div></div>, container);
484+
`,
485+
errors: [
486+
errorMessage(
487+
'ReactDOM.render',
488+
'18.0.0',
489+
'createRoot',
490+
'https://reactjs.org/link/switch-to-createroot',
491+
{ type: 'ImportDeclaration', line: 2, column: 9 }
492+
),
493+
errorMessage(
494+
'ReactDOM.render',
495+
'18.0.0',
496+
'createRoot',
497+
'https://reactjs.org/link/switch-to-createroot',
498+
{ type: 'MemberExpression', line: 3, column: 9 }
499+
),
500+
],
501+
},
502+
{
503+
code: `
504+
import { hydrate } from 'react-dom';
505+
ReactDOM.hydrate(<div></div>, container);
506+
`,
507+
errors: [
508+
errorMessage(
509+
'ReactDOM.hydrate',
510+
'18.0.0',
511+
'hydrateRoot',
512+
'https://reactjs.org/link/switch-to-createroot',
513+
{ type: 'ImportDeclaration', line: 2, column: 9 }
514+
),
515+
errorMessage(
516+
'ReactDOM.hydrate',
517+
'18.0.0',
518+
'hydrateRoot',
519+
'https://reactjs.org/link/switch-to-createroot',
520+
{ type: 'MemberExpression', line: 3, column: 9 }
521+
),
522+
],
523+
},
524+
{
525+
code: `
526+
import { unmountComponentAtNode } from 'react-dom';
527+
ReactDOM.unmountComponentAtNode(container);
528+
`,
529+
errors: [
530+
errorMessage(
531+
'ReactDOM.unmountComponentAtNode',
532+
'18.0.0',
533+
'root.unmount',
534+
'https://reactjs.org/link/switch-to-createroot',
535+
{ type: 'ImportDeclaration', line: 2, column: 9 }
536+
),
537+
errorMessage(
538+
'ReactDOM.unmountComponentAtNode',
539+
'18.0.0',
540+
'root.unmount',
541+
'https://reactjs.org/link/switch-to-createroot',
542+
{ type: 'MemberExpression', line: 3, column: 9 }
543+
),
544+
],
545+
},
546+
{
547+
code: `
548+
import { renderToNodeStream } from 'react-dom/server';
549+
ReactDOMServer.renderToNodeStream(element);
550+
`,
551+
errors: [
552+
errorMessage(
553+
'ReactDOMServer.renderToNodeStream',
554+
'18.0.0',
555+
'renderToPipeableStream',
556+
'https://reactjs.org/docs/react-dom-server.html#rendertonodestream',
557+
{ type: 'ImportDeclaration', line: 2, column: 9 }
558+
),
559+
errorMessage(
560+
'ReactDOMServer.renderToNodeStream',
561+
'18.0.0',
562+
'renderToPipeableStream',
563+
'https://reactjs.org/docs/react-dom-server.html#rendertonodestream',
564+
{ type: 'MemberExpression', line: 3, column: 9 }
565+
),
566+
],
567+
},
457568
]),
458569
});

0 commit comments

Comments
 (0)