Skip to content

Commit 3fb79e1

Browse files
pnodetljharb
authored andcommitted
[New] prefer-read-only-props, prop-types, component detection: allow components to be async functions
1 parent 9ff9ef9 commit 3fb79e1

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
1010
* [`no-invalid-html-attribute`]: add support for `apple-touch-startup-image` `rel` attributes in `link` tags ([#3638][] @thomashockaday)
1111
* [`no-unknown-property`]: add requireDataLowercase option ([#3645][] @HermanBilous)
1212
* [`no-unknown-property`]: add `displaystyle` on `<math>` ([#3652][] @lounsbrough)
13+
* [`prefer-read-only-props`], [`prop-types`], component detection: allow components to be async functions ([#3654][] @pnodet)
1314

1415
### Fixed
1516
* [`jsx-no-leaked-render`]: preserve RHS parens for multiline jsx elements while fixing ([#3623][] @akulsr0)
@@ -22,6 +23,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
2223
* [Refactor] [`function-component-definition`]: exit early if no type params ([#3634][] @HenryBrown0)
2324
* [Refactor] [`jsx-props-no-multi-spaces`]: extract type parameters to var ([#3634][] @HenryBrown0)
2425

26+
[#3654]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3654
2527
[#3652]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3652
2628
[#3645]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3645
2729
[#3638]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3638

lib/util/Components.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ function componentRule(rule, context) {
855855
},
856856

857857
FunctionExpression(node) {
858-
if (node.async) {
858+
if (node.async && node.generator) {
859859
components.add(node, 0);
860860
return;
861861
}
@@ -868,7 +868,7 @@ function componentRule(rule, context) {
868868
},
869869

870870
FunctionDeclaration(node) {
871-
if (node.async) {
871+
if (node.async && node.generator) {
872872
components.add(node, 0);
873873
return;
874874
}
@@ -881,11 +881,6 @@ function componentRule(rule, context) {
881881
},
882882

883883
ArrowFunctionExpression(node) {
884-
if (node.async) {
885-
components.add(node, 0);
886-
return;
887-
}
888-
889884
const component = utils.getStatelessComponent(node);
890885
if (!component) {
891886
return;

tests/lib/rules/prefer-read-only-props.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,19 @@ ruleTester.run('prefer-read-only-props', rule, {
218218
`,
219219
features: ['ts', 'no-babel-old'],
220220
},
221+
{
222+
code: `
223+
import React from "react";
224+
type Props = {
225+
readonly name: string[];
226+
}
227+
const MyComponent: React.FC<Props> = async ({ name }) => {
228+
return <div>{name}</div>;
229+
};
230+
export default MyComponent;
231+
`,
232+
features: ['ts', 'no-babel-old'],
233+
},
221234
{
222235
code: `
223236
import React from "react";
@@ -500,6 +513,35 @@ ruleTester.run('prefer-read-only-props', rule, {
500513
},
501514
],
502515
},
516+
{
517+
code: `
518+
import React from "react";
519+
type Props = {
520+
name: string[];
521+
}
522+
const MyComponent: React.FC<Props> = async ({ name }) => {
523+
return <div>{name}</div>;
524+
};
525+
export default MyComponent;
526+
`,
527+
output: `
528+
import React from "react";
529+
type Props = {
530+
readonly name: string[];
531+
}
532+
const MyComponent: React.FC<Props> = async ({ name }) => {
533+
return <div>{name}</div>;
534+
};
535+
export default MyComponent;
536+
`,
537+
features: ['ts', 'no-babel-old'],
538+
errors: [
539+
{
540+
messageId: 'readOnlyProp',
541+
data: { name: 'name' },
542+
},
543+
],
544+
},
503545
{
504546
code: `
505547
type Props = {

tests/lib/rules/prop-types.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,25 +1571,28 @@ ruleTester.run('prop-types', rule, {
15711571
options: [{ skipUndeclared: false }],
15721572
},
15731573
{
1574-
// Async functions can't be components.
1574+
// Async generator functions can't be components.
15751575
code: `
1576-
var Hello = async function(props) {
1576+
var Hello = async function* (props) {
1577+
yield null;
15771578
return <div>Hello {props.name}</div>;
15781579
}
15791580
`,
15801581
},
15811582
{
1582-
// Async functions can't be components.
1583+
// Async generator functions can't be components.
15831584
code: `
1584-
async function Hello(props) {
1585+
async function* Hello(props) {
1586+
yield null;
15851587
return <div>Hello {props.name}</div>;
15861588
}
15871589
`,
15881590
},
15891591
{
1590-
// Async functions can't be components.
1592+
// Async generator functions can't be components.
15911593
code: `
1592-
var Hello = async (props) => {
1594+
var Hello = async function* (props) {
1595+
yield null;
15931596
return <div>Hello {props.name}</div>;
15941597
}
15951598
`,

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