Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
> **isDeclaredInRenderPropLoose**(`node`): `boolean`

Unsafe check whether given node is declared inside a render prop
```jsx
```tsx
_ = <Component renderRow={"node"} />
` ^^^^^^ `
_ = <Component rows={ [{ render: "node" }] } />
Expand Down
2 changes: 1 addition & 1 deletion packages/core/docs/functions/isInsideRenderMethod.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
> **isInsideRenderMethod**(`node`): `boolean`

Check whether given node is declared inside class component's render block
```jsx
```tsx
class Component extends React.Component {
render() {
class NestedClassComponent extends React.Component {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/docs/functions/isRenderFunctionLoose.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
> **isRenderFunctionLoose**(`context`, `node`): `boolean`

Unsafe check whether given node is a render function
```jsx
```tsx
const renderRow = () => <div />
` ^^^^^^^^^^^^`
_ = <Component renderRow={() => <div />} />
Expand Down
2 changes: 1 addition & 1 deletion packages/core/docs/functions/isRenderPropLoose.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
> **isRenderPropLoose**(`context`, `node`): `boolean`

Unsafe check whether given JSXAttribute is a render prop
```jsx
```tsx
_ = <Component renderRow={() => <div />} />
` ^^^^^^^^^^^^^^^^^^^^^^^^^ `
```
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/component/component-lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function isFunctionOfRenderMethod(node: AST.TSESTreeFunction) {

/**
* Check whether given node is declared inside class component's render block
* ```jsx
* ```tsx
* class Component extends React.Component {
* render() {
* class NestedClassComponent extends React.Component {
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/component/component-render-prop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AST_NODE_TYPES as T } from "@typescript-eslint/types";

/**
* Unsafe check whether given node is a render function
* ```jsx
* ```tsx
* const renderRow = () => <div />
* ` ^^^^^^^^^^^^`
* _ = <Component renderRow={() => <div />} />
Expand Down Expand Up @@ -39,7 +39,7 @@ export function isRenderFunctionLoose(context: RuleContext, node: AST.TSESTreeFu

/**
* Unsafe check whether given JSXAttribute is a render prop
* ```jsx
* ```tsx
* _ = <Component renderRow={() => <div />} />
* ` ^^^^^^^^^^^^^^^^^^^^^^^^^ `
* ```
Expand All @@ -59,7 +59,7 @@ export function isRenderPropLoose(context: RuleContext, node: TSESTree.JSXAttrib

/**
* Unsafe check whether given node is declared directly inside a render property
* ```jsx
* ```tsx
* const rows = { render: () => <div /> }
* ` ^^^^^^^^^^^^^ `
* _ = <Component rows={ [{ render: () => <div /> }] } />
Expand All @@ -80,7 +80,7 @@ export function isDirectValueOfRenderPropertyLoose(node: TSESTree.Node) {

/**
* Unsafe check whether given node is declared inside a render prop
* ```jsx
* ```tsx
* _ = <Component renderRow={"node"} />
* ` ^^^^^^ `
* _ = <Component rows={ [{ render: "node" }] } />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,19 @@ A **safe** auto-fix is available for this rule.
### Failing

```tsx
import React from "react";

function MyComponent() {
return <button disabled />;
// ^^^^^^^^
// - Avoid using shorthand syntax for 'disabled' attribute.
}
const Input = <input type="checkbox" checked />;
// ^^^^^^^
// - Expected `checked={true}` instead of `checked`
const button = <button disabled />;
// ^^^^^^^^
// - Expected `disabled={true}` instead of `disabled`
```

### Passing

```tsx
import React from "react";

function MyComponent() {
return <button disabled={true} />;
}
const Input = <input type="checkbox" checked={true} />;
const button = <button disabled={true} />;
```

## Implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Enforces explicit `<Fragment>` components instead of the shorthand `<>` or `</>`
```tsx
import React from "react";

function MyComponent() {
export function MyComponent() {
return (
<>
<button />
Expand All @@ -40,7 +40,7 @@ function MyComponent() {
```tsx
import React, { Fragment } from "react";

function MyComponent() {
export function MyComponent() {
return (
<Fragment>
<button />
Expand Down
39 changes: 10 additions & 29 deletions packages/plugins/eslint-plugin-react-x/src/rules/jsx-no-undef.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,21 @@ This rule is used to prevent the use of undefined variables in JSX. It checks fo

### Failing

```jsx
const MyComponent = () => {
return (
<div>
<Foo />
</div>
);
};
```tsx
import React from "react";

const button = <MyButton />;
// ^^^^^^^^
// - 'MyButton' is not defined
```

### Passing

```jsx
import Foo from "./Foo";

const MyComponent = () => {
return (
<div>
<Foo />
</div>
);
};
```

```jsx
const Foo = () => <div>Foo</div>;
```tsx
import React from "react";
import MyButton from "./MyButton";

const MyComponent = () => {
return (
<div>
<Foo />
</div>
);
};
const button = <MyButton />;
```

## Implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ This rule only has an effect when the `no-unused-vars` rule is enabled.
### Failing

```tsx
const Hello = require("./Hello");
import Hello from "./Hello";
```

### Passing

```tsx
const Hello = require("./Hello");
import Hello from "./Hello";

<Hello name="John" />;
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,31 @@ function MyComponent({ name }: MyComponentProps) {
}
```

```tsx
import React, { Component } from "react";

interface ErrorBoundaryProps {
children: React.ReactNode;
}

// This is an exception to the rule, as ErrorBoundary is a special case.
class ErrorBoundary extends Component<ErrorBoundaryProps> {
state = { hasError: false };

static getDerivedStateFromError(error: Error) {
return { hasError: true };
}

render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}

return this.props.children;
}
}
```

## Implementation

- [Rule source](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x/src/rules/no-class-component.ts)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This could be a mistake during code editing or it could be a misunderstanding of
```tsx
import React from "react";

function MyComponent() {
function MyComponent1() {
return <div>// empty div</div>;
// ^^^^^^^^^^^^
// - Possible misused comment in text node. Comments inside children section of tag should be placed inside braces.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ A **safe** codemod is available for this rule.
### Failing

```tsx
const ThemeContext = createContext("");
import React from "react";
import ThemeContext from "./ThemeContext";

function App({ children }) {
return (
Expand All @@ -54,7 +55,8 @@ function App({ children }) {
### Passing

```tsx
const ThemeContext = createContext("");
import React from "react";
import ThemeContext from "./ThemeContext";

function App({ children }) {
return (
Expand Down
41 changes: 29 additions & 12 deletions packages/plugins/eslint-plugin-react-x/src/rules/no-forward-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ An **unsafe** codemod is available for this rule.
### Failing

```tsx
import { forwardRef } from "react";
import React, { forwardRef } from "react";

const MyInput = forwardRef(function MyInput(props, ref) {
return <input ref={ref} {...props} />;
});
const MyInput = forwardRef(
function MyInput(props, ref) {
return <input ref={ref} {...props} />;
},
);
```

```tsx
Expand All @@ -55,12 +57,17 @@ interface MyInputProps {
onChange: (value: string) => void;
}

const MyInput = React.forwardRef<MyInputProps, HTMLInputElement>(function MyInput(
{ value, onChange },
ref,
) {
return <input ref={ref} value={value} onChange={(e) => onChange(e.target.value)} />;
});
const MyInput = React.forwardRef<MyInputProps, HTMLInputElement>(
function MyInput({ value, onChange }, ref) {
return (
<input
ref={ref}
value={value}
onChange={(e) => onChange(e.target.value)}
/>
);
},
);
```

### Passing
Expand All @@ -79,8 +86,18 @@ interface MyInputProps {
onChange: (value: string) => void;
}

function MyInput({ ref, value, onChange }: MyInputProps & { ref: React.RefObject<HTMLInputElement> }) {
return <input ref={ref} value={value} onChange={(e) => onChange(e.target.value)} />;
function MyInput({
ref,
value,
onChange,
}: MyInputProps & { ref: React.RefObject<HTMLInputElement> }) {
return (
<input
ref={ref}
value={value}
onChange={(e) => onChange(e.target.value)}
/>
);
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ function MyComponent({ items }: MyComponentProps) {
return (
<ul>
{items.map((todo) => (
<Todo {...todo} />
{/* ^^^^^^^^^^^^^^^ */}
{/* - Missing 'key' for element when rendering list. */}
<Todo
{...todo}
/>
))}
</ul>
);
Expand All @@ -63,7 +63,12 @@ interface MyComponentProps {
function MyComponent({ items }: MyComponentProps) {
return (
<ul>
{items.map((todo) => <Todo key={todo.id} {...todo} />)}
{items.map((todo) => (
<Todo
key={todo.id}
{...todo}
/>
))}
</ul>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ interface MyComponentProps {
}

function MyComponent({ num = 3, str = "foo", bool = true }: MyComponentProps) {
// -------------------------------------
// - Primitives are all compared by value, so are safe to be inlined as default props.
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// - Primitives are all compared by value, so are safe to be inlined as default props.
return null;
}
```
Expand Down