diff --git a/crates/oxc_linter/src/rules/react/jsx_no_comment_textnodes.rs b/crates/oxc_linter/src/rules/react/jsx_no_comment_textnodes.rs index 520d817bbae08..8aab2df33b52d 100644 --- a/crates/oxc_linter/src/rules/react/jsx_no_comment_textnodes.rs +++ b/crates/oxc_linter/src/rules/react/jsx_no_comment_textnodes.rs @@ -20,30 +20,32 @@ pub struct JsxNoCommentTextnodes; declare_oxc_lint!( /// ### What it does /// - /// This rule prevents comment strings (e.g. beginning with `//` or `/*`) from being accidentally injected as a text node in JSX statements. + /// This rule prevents comment strings (e.g. beginning with `//` or `/*`) from being + /// accidentally injected as a text node in JSX statements. /// /// ### Why is this bad? /// - /// In JSX, any text node that is not wrapped in curly braces is considered a literal string to be rendered. This can lead to unexpected behavior when the text contains a comment. + /// In JSX, any text node that is not wrapped in curly braces is considered + /// a literal string to be rendered. This can lead to unexpected behavior + /// when the text contains a comment. /// /// ### Examples /// /// Examples of **incorrect** code for this rule: /// ```jsx /// const Hello = () => { - /// return
// empty div
; + /// return
// empty div
; /// } /// /// const Hello = () => { - /// return
/* empty div */
; + /// return
/* empty div */
; /// } - /// /// ``` /// /// Examples of **correct** code for this rule: /// ```jsx /// const Hello = () => { - /// return
{/* empty div */}
; + /// return
{/* empty div */}
; /// } /// ``` JsxNoCommentTextnodes, diff --git a/crates/oxc_linter/src/rules/react/no_did_mount_set_state.rs b/crates/oxc_linter/src/rules/react/no_did_mount_set_state.rs index 34d654da11d34..6d54eab5dec66 100644 --- a/crates/oxc_linter/src/rules/react/no_did_mount_set_state.rs +++ b/crates/oxc_linter/src/rules/react/no_did_mount_set_state.rs @@ -21,9 +21,10 @@ fn no_did_mount_set_state_diagnostic(span: Span) -> OxcDiagnostic { #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "kebab-case")] pub enum NoDidMountSetStateConfig { + /// Allow `setState` calls in nested functions within `componentDidMount`, the default behavior. #[default] - #[serde(skip)] Allowed, + /// When set, also disallows `setState` calls in nested functions within `componentDidMount`. DisallowInFunc, } @@ -35,6 +36,9 @@ declare_oxc_lint!( /// /// Disallows using `setState` in the `componentDidMount` lifecycle method. /// + /// This rule is not relevant for function components, and so can potentially be + /// disabled for modern React codebases. + /// /// ### Why is this bad? /// /// Updating the state after a component mount will trigger a second `render()` call and can lead to property/layout thrashing. @@ -71,18 +75,6 @@ declare_oxc_lint!( /// } /// }); /// ``` - /// - /// ### Options - /// - /// The rule accepts a string value `"disallow-in-func"`: - /// - /// ```json - /// { - /// "react/no-did-mount-set-state": ["error", "disallow-in-func"] - /// } - /// ``` - /// - /// When set, also disallows `setState` calls in nested functions within `componentDidMount`. NoDidMountSetState, react, correctness, diff --git a/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs b/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs index 14f5f17696bd4..e4fcfd3959c6b 100644 --- a/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs +++ b/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs @@ -12,8 +12,10 @@ use crate::{ }; fn no_direct_mutation_state_diagnostic(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("never mutate this.state directly.") - .with_help("calling setState() afterwards may replace the mutation you made.") + OxcDiagnostic::warn("Never mutate `this.state` directly.") + .with_help( + "Calling `setState()` afterwards will replace the mutations you made via `this.state`.", + ) .with_label(span) } @@ -27,55 +29,64 @@ pub struct NoDirectMutationState; declare_oxc_lint!( /// ### What it does /// - /// The restriction coder cannot directly change the value of this.state + /// This rule forbids the direct mutation of `this.state` in React components. + /// + /// Note that this rule only applies to class components, it does not apply to function + /// components. For modern React codebases, this rule may not be necessary or relevant. /// /// ### Why is this bad? /// - /// calling setState() afterwards may replace the mutation you made + /// React components should *never* mutate `this.state` directly, as + /// calling `setState()` afterwards may replace the mutation you made. + /// + /// `this.state` should be treated as if it were immutable. /// /// ### Examples + /// + /// Examples of **incorrect** code for this rule: /// ```jsx - /// // error - /// var Hello = createReactClass({ - /// componentDidMount: function() { - /// this.state.name = this.props.name.toUpperCase(); - /// }, - /// render: function() { - /// return
Hello {this.state.name}
; - /// } - /// }); + /// var Hello = createReactClass({ + /// componentDidMount: function() { + /// this.state.name = this.props.name.toUpperCase(); + /// }, + /// render: function() { + /// return
Hello {this.state.name}
; + /// } + /// }); /// - /// class Hello extends React.Component { - /// constructor(props) { - /// super(props) + /// class Hello extends React.Component { + /// constructor(props) { + /// super(props) /// - /// doSomethingAsync(() => { - /// this.state = 'bad'; - /// }); - /// } - /// } + /// doSomethingAsync(() => { + /// this.state = 'bad'; + /// }); + /// } + /// } + /// ``` /// - /// // success - /// var Hello = createReactClass({ - /// componentDidMount: function() { - /// this.setState({ - /// name: this.props.name.toUpperCase(); - /// }); - /// }, - /// render: function() { - /// return
Hello {this.state.name}
; - /// } - /// }); + /// Examples of **correct** code for this rule: + /// ```jsx + /// var Hello = createReactClass({ + /// componentDidMount: function() { + /// this.setState({ + /// name: this.props.name.toUpperCase(); + /// }); + /// }, + /// render: function() { + /// return
Hello {this.state.name}
; + /// } + /// }); /// - /// class Hello extends React.Component { - /// constructor(props) { - /// super(props) + /// class Hello extends React.Component { + /// constructor(props) { + /// super(props) /// - /// this.state = { - /// foo: 'bar', - /// } - /// } - /// } + /// this.state = { + /// foo: 'bar', + /// } + /// } + /// } /// ``` NoDirectMutationState, react, diff --git a/crates/oxc_linter/src/rules/react/no_redundant_should_component_update.rs b/crates/oxc_linter/src/rules/react/no_redundant_should_component_update.rs index 5c50cfd8b66ac..2b86a989e38cd 100644 --- a/crates/oxc_linter/src/rules/react/no_redundant_should_component_update.rs +++ b/crates/oxc_linter/src/rules/react/no_redundant_should_component_update.rs @@ -26,6 +26,9 @@ declare_oxc_lint!( /// /// Disallow usage of `shouldComponentUpdate` when extending `React.PureComponent`. /// + /// Note that usage of `PureComponent` is + /// [not recommended in modern React](https://react.dev/reference/react/PureComponent). + /// /// ### Why is this bad? /// /// `React.PureComponent` automatically implements `shouldComponentUpdate` with a shallow prop and state comparison. diff --git a/crates/oxc_linter/src/rules/react/no_render_return_value.rs b/crates/oxc_linter/src/rules/react/no_render_return_value.rs index f5427eb234958..95edfabea5b99 100644 --- a/crates/oxc_linter/src/rules/react/no_render_return_value.rs +++ b/crates/oxc_linter/src/rules/react/no_render_return_value.rs @@ -25,15 +25,20 @@ declare_oxc_lint!( /// /// ### Why is this bad? /// - /// Using the return value from `ReactDOM.render()` is a legacy feature and should not be used. + /// Using the return value from `ReactDOM.render()` is a legacy + /// feature and should not be used. + /// + /// Note that `ReactDOM.render` + /// [has been removed entirely in React 19](https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-reactdom-render) + /// and so should generally not be used. /// /// ### Examples /// /// Examples of **incorrect** code for this rule: /// ```jsx - /// vaa inst =ReactDOM.render(, document.body); + /// var inst = ReactDOM.render(, document.body); /// function render() { - /// return ReactDOM.render(, document.body); + /// return ReactDOM.render(, document.body); /// } /// ``` /// diff --git a/crates/oxc_linter/src/rules/react/require_render_return.rs b/crates/oxc_linter/src/rules/react/require_render_return.rs index 01d1c7c8e66b2..7b03f2d33142a 100644 --- a/crates/oxc_linter/src/rules/react/require_render_return.rs +++ b/crates/oxc_linter/src/rules/react/require_render_return.rs @@ -15,8 +15,8 @@ use crate::{ }; fn require_render_return_diagnostic(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Your render method should have a return statement") - .with_help("When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing.") + OxcDiagnostic::warn("Your `render` method should have a `return` statement.") + .with_help("When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the `return` statement is missing.") .with_label(span) } @@ -26,11 +26,15 @@ pub struct RequireRenderReturn; declare_oxc_lint!( /// ### What it does /// - /// Enforce ES5 or ES2015 class for returning value in render function + /// Enforce ES5 or ES2015 class for returning value in the `render` function. + /// + /// This rule is not relevant for function components, and so can potentially be + /// disabled for modern React codebases. /// /// ### Why is this bad? /// - /// When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing. + /// When writing the `render` method in a component it is easy to forget to return the + /// JSX content. This rule will warn if the `return` statement is missing. /// /// ### Examples /// diff --git a/crates/oxc_linter/src/rules/react/self_closing_comp.rs b/crates/oxc_linter/src/rules/react/self_closing_comp.rs index 947faeb82139b..717109e1cf1c4 100644 --- a/crates/oxc_linter/src/rules/react/self_closing_comp.rs +++ b/crates/oxc_linter/src/rules/react/self_closing_comp.rs @@ -355,6 +355,7 @@ fn test() { Some(serde_json::json!([{ "html": true }])), ), ]; + Tester::new(SelfClosingComp::NAME, SelfClosingComp::PLUGIN, pass, fail) .expect_fix(fix) .test_and_snapshot(); diff --git a/crates/oxc_linter/src/rules/react/state_in_constructor.rs b/crates/oxc_linter/src/rules/react/state_in_constructor.rs index 6641515e8c0d9..9ad765795c6a4 100644 --- a/crates/oxc_linter/src/rules/react/state_in_constructor.rs +++ b/crates/oxc_linter/src/rules/react/state_in_constructor.rs @@ -27,6 +27,7 @@ fn state_in_constructor_diagnostic(span: Span, is_state_init_constructor: bool) #[serde(rename_all = "kebab-case")] pub enum StateInConstructorConfig { /// Enforce state initialization in the constructor. + /// This is the default mode. #[default] Always, /// Enforce state initialization with a class property. @@ -57,7 +58,11 @@ impl std::ops::Deref for StateInConstructor { declare_oxc_lint!( /// ### What it does /// - /// Enforces the state initialization style to be either in a constructor or with a class property. + /// Enforces the state initialization style to be either in a + /// constructor or with a class property. + /// + /// This rule is not relevant for function components, and so can potentially be + /// disabled for modern React codebases. /// /// ### Why is this bad? /// @@ -66,13 +71,7 @@ declare_oxc_lint!( /// /// ### Examples /// - /// This rule has two modes: `"always"` and `"never"`. - /// - /// #### `"always"` mode - /// - /// Will enforce the state initialization style to be in a constructor. This is the default mode. - /// - /// Examples of **incorrect** code for this rule: + /// Examples of **incorrect** code for this rule by default, with `"always"` mode: /// ```jsx /// class Foo extends React.Component { /// state = { bar: 0 } @@ -82,7 +81,7 @@ declare_oxc_lint!( /// } /// ``` /// - /// Examples of **correct** code for this rule: + /// Examples of **correct** code for this rule by default, with `"always"` mode: /// ```jsx /// class Foo extends React.Component { /// constructor(props) { @@ -99,7 +98,7 @@ declare_oxc_lint!( /// /// Will enforce the state initialization style to be with a class property. /// - /// Examples of **incorrect** code for this rule: + /// Examples of **incorrect** code for this rule with `"never"` mode: /// ```jsx /// class Foo extends React.Component { /// constructor(props) { @@ -112,7 +111,7 @@ declare_oxc_lint!( /// } /// ``` /// - /// Examples of **correct** code for this rule: + /// Examples of **correct** code for this rule with `"never"` mode: /// ```jsx /// class Foo extends React.Component { /// state = { bar: 0 } diff --git a/crates/oxc_linter/src/snapshots/react_no_direct_mutation_state.snap b/crates/oxc_linter/src/snapshots/react_no_direct_mutation_state.snap index d6a31c3493de9..610ddc4e1310e 100644 --- a/crates/oxc_linter/src/snapshots/react_no_direct_mutation_state.snap +++ b/crates/oxc_linter/src/snapshots/react_no_direct_mutation_state.snap @@ -1,155 +1,155 @@ --- source: crates/oxc_linter/src/tester.rs --- - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:5:23] 4 │ componentWillMount() { 5 │ this.state.foo = "Chicken, you're so beautiful" · ────────────── 6 │ }, ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:9:29] 8 │ render: function() { 9 │ this.state.foo = "Chicken, you're so beautiful" · ────────────── 10 │ return
Hello{this.props.name}
; ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:16:30] 15 │ render: () => { 16 │ this.state.foo = "Chicken, you're so beautiful" · ────────────── 17 │ return
Hello {this.props.name}
; ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:22] 3 │ render: function() { 4 │ this.state.foo++; · ──────────────── 5 │ return
Hello {this.props.name}
; ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:13] 3 │ render: function() { 4 │ this.state.person.name= "bar" · ────────────────────── 5 │ return
Hello {this.props.name}
; ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ render: function() { 4 │ this.state.person.name.first = "bar" · ──────────────────────────── 5 │ return
Hello
; ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ render: function() { 4 │ this.state.person.name.first = "bar" · ──────────────────────────── 5 │ this.state.person.name.last = "baz" ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:5:15] 4 │ this.state.person.name.first = "bar" 5 │ this.state.person.name.last = "baz" · ─────────────────────────── 6 │ return
Hello
; ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:7:15] 6 │ someFn() { 7 │ this.state.foo = "bar" · ────────────── 8 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:6:17] 5 │ doSomethingAsync(() => { 6 │ this.state = "bad"; · ────────── 7 │ }); ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ componentWillMount() { 4 │ this.state.foo = "bar" · ────────────── 5 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ componentDidMount() { 4 │ this.state.foo = "bar" · ────────────── 5 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ componentWillReceiveProps() { 4 │ this.state.foo = "bar" · ────────────── 5 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ shouldComponentUpdate() { 4 │ this.state.foo = "bar" · ────────────── 5 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ componentWillUpdate() { 4 │ this.state.foo = "bar" · ────────────── 5 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ componentDidUpdate() { 4 │ this.state.foo = "bar" · ────────────── 5 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. - ⚠ eslint-plugin-react(no-direct-mutation-state): never mutate this.state directly. + ⚠ eslint-plugin-react(no-direct-mutation-state): Never mutate `this.state` directly. ╭─[no_direct_mutation_state.tsx:4:15] 3 │ componentWillUnmount() { 4 │ this.state.foo = "bar" · ────────────── 5 │ } ╰──── - help: calling setState() afterwards may replace the mutation you made. + help: Calling `setState()` afterwards will replace the mutations you made via `this.state`. diff --git a/crates/oxc_linter/src/snapshots/react_require_render_return.snap b/crates/oxc_linter/src/snapshots/react_require_render_return.snap index 73a3930b6c9d8..b4f6091140a38 100644 --- a/crates/oxc_linter/src/snapshots/react_require_render_return.snap +++ b/crates/oxc_linter/src/snapshots/react_require_render_return.snap @@ -1,56 +1,56 @@ --- source: crates/oxc_linter/src/tester.rs --- - ⚠ eslint-plugin-react(require-render-return): Your render method should have a return statement + ⚠ eslint-plugin-react(require-render-return): Your `render` method should have a `return` statement. ╭─[require_render_return.tsx:4:20] 3 │ displayName: 'Hello', 4 │ render: function() {} · ────── 5 │ }); ╰──── - help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing. + help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the `return` statement is missing. - ⚠ eslint-plugin-react(require-render-return): Your render method should have a return statement + ⚠ eslint-plugin-react(require-render-return): Your `render` method should have a `return` statement. ╭─[require_render_return.tsx:3:20] 2 │ class Hello extends React.Component { 3 │ render() {} · ────── 4 │ } ╰──── - help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing. + help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the `return` statement is missing. - ⚠ eslint-plugin-react(require-render-return): Your render method should have a return statement + ⚠ eslint-plugin-react(require-render-return): Your `render` method should have a `return` statement. ╭─[require_render_return.tsx:3:20] 2 │ class Hello extends React.Component { 3 │ render() { · ────── 4 │ const names = this.props.names.map(function(name) { ╰──── - help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing. + help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the `return` statement is missing. - ⚠ eslint-plugin-react(require-render-return): Your render method should have a return statement + ⚠ eslint-plugin-react(require-render-return): Your `render` method should have a `return` statement. ╭─[require_render_return.tsx:3:20] 2 │ class Hello extends React.Component { 3 │ render = () => { · ────── 4 │
Hello {this.props.name}
╰──── - help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing. + help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the `return` statement is missing. - ⚠ eslint-plugin-react(require-render-return): Your render method should have a return statement + ⚠ eslint-plugin-react(require-render-return): Your `render` method should have a `return` statement. ╭─[require_render_return.tsx:3:15] 2 │ class Hello extends React.Component { 3 │ render() { · ────── 4 │ function foo() { ╰──── - help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing. + help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the `return` statement is missing. - ⚠ eslint-plugin-react(require-render-return): Your render method should have a return statement + ⚠ eslint-plugin-react(require-render-return): Your `render` method should have a `return` statement. ╭─[require_render_return.tsx:3:15] 2 │ class Hello extends React.Component { 3 │ render() { · ────── 4 │ return ╰──── - help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the return statement is missing. + help: When writing the `render` method in a component it is easy to forget to return the JSX content. This rule will warn if the `return` statement is missing.