Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
77 changes: 40 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,56 +88,59 @@ export default [

<!-- begin auto-generated rules list -->

🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).

### debug

| Name | Description |
| :--------------------------------------------------------------------------------------- | :-------------------------------------------------------- |
| [debug/class-component](packages/eslint-plugin-debug/src/rules/class-component.md) | reports all class components, including anonymous ones |
| [debug/function-component](packages/eslint-plugin-debug/src/rules/function-component.md) | reports all function components, including anonymous ones |
| [debug/hooks](packages/eslint-plugin-debug/src/rules/hooks.md) | reports all react hooks |
| Name | Description | 🔧 |
| :--------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :- |
| [debug/class-component](packages/eslint-plugin-debug/src/rules/class-component.md) | reports all class components, including anonymous ones | |
| [debug/function-component](packages/eslint-plugin-debug/src/rules/function-component.md) | reports all function components, including anonymous ones | |
| [debug/hooks](packages/eslint-plugin-debug/src/rules/hooks.md) | reports all react hooks | |

### hooks

| Name | Description |
| :----------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- |
| [hooks/ensure-custom-hooks-using-other-hooks](packages/eslint-plugin-hooks/src/rules/ensure-custom-hooks-using-other-hooks.md) | enforce custom hooks using other hooks |
| Name | Description | 🔧 |
| :----------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- | :- |
| [hooks/ensure-custom-hooks-using-other-hooks](packages/eslint-plugin-hooks/src/rules/ensure-custom-hooks-using-other-hooks.md) | enforce custom hooks using other hooks | |

### jsx

| Name                                | Description |
| :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ |
| [jsx/no-array-index-key](packages/eslint-plugin-jsx/src/rules/no-array-index-key.md) | disallow using Array index as key |
| [jsx/no-duplicate-key](packages/eslint-plugin-jsx/src/rules/no-duplicate-key.md) | disallow duplicate keys in `key` prop when rendering list |
| [jsx/no-leaked-conditional-rendering](packages/eslint-plugin-jsx/src/rules/no-leaked-conditional-rendering.md) | disallow problematic leaked values from being rendered |
| [jsx/no-missing-key](packages/eslint-plugin-jsx/src/rules/no-missing-key.md) | require `key` prop when rendering list |
| [jsx/no-misused-comment-in-textnode](packages/eslint-plugin-jsx/src/rules/no-misused-comment-in-textnode.md) | disallow comments from being inserted as text nodes |
| [jsx/no-script-url](packages/eslint-plugin-jsx/src/rules/no-script-url.md) | disallow `javascript:` URLs as JSX event handler prop's value |
| [jsx/prefer-shorthand-boolean](packages/eslint-plugin-jsx/src/rules/prefer-shorthand-boolean.md) | enforce boolean attributes notation in JSX |
| Name                                | Description | 🔧 |
| :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ | :- |
| [jsx/no-array-index-key](packages/eslint-plugin-jsx/src/rules/no-array-index-key.md) | disallow using Array index as key | |
| [jsx/no-duplicate-key](packages/eslint-plugin-jsx/src/rules/no-duplicate-key.md) | disallow duplicate keys in `key` prop when rendering list | |
| [jsx/no-leaked-conditional-rendering](packages/eslint-plugin-jsx/src/rules/no-leaked-conditional-rendering.md) | disallow problematic leaked values from being rendered | |
| [jsx/no-missing-key](packages/eslint-plugin-jsx/src/rules/no-missing-key.md) | require `key` prop when rendering list | |
| [jsx/no-misused-comment-in-textnode](packages/eslint-plugin-jsx/src/rules/no-misused-comment-in-textnode.md) | disallow comments from being inserted as text nodes | |
| [jsx/no-script-url](packages/eslint-plugin-jsx/src/rules/no-script-url.md) | disallow `javascript:` URLs as JSX event handler prop's value | |
| [jsx/no-useless-fragment](packages/eslint-plugin-jsx/src/rules/no-useless-fragment.md) | disallow unnecessary fragments | 🔧 |
| [jsx/prefer-shorthand-boolean](packages/eslint-plugin-jsx/src/rules/prefer-shorthand-boolean.md) | enforce boolean attributes notation in JSX | |

### naming-convention

| Name | Description |
| :--------------------------------------------------------------------------------------------------------------- | :------------------------------------------------ |
| [naming-convention/filename](packages/eslint-plugin-naming-convention/src/rules/filename.md) | enforce naming convention for JSX file names |
| [naming-convention/filename-extension](packages/eslint-plugin-naming-convention/src/rules/filename-extension.md) | enforce naming convention for JSX file extensions |
| Name | Description | 🔧 |
| :--------------------------------------------------------------------------------------------------------------- | :------------------------------------------------ | :- |
| [naming-convention/filename](packages/eslint-plugin-naming-convention/src/rules/filename.md) | enforce naming convention for JSX file names | |
| [naming-convention/filename-extension](packages/eslint-plugin-naming-convention/src/rules/filename-extension.md) | enforce naming convention for JSX file extensions | |

### react

| Name                                             | Description |
| :--------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------ |
| [react/no-children-in-void-dom-elements](packages/eslint-plugin-react/src/rules/no-children-in-void-dom-elements.md) | disallow passing children to void DOM elements |
| [react/no-class-component](packages/eslint-plugin-react/src/rules/no-class-component.md) | enforce that there are no class components |
| [react/no-clone-element](packages/eslint-plugin-react/src/rules/no-clone-element.md) | disallow `cloneElement` |
| [react/no-constructed-context-value](packages/eslint-plugin-react/src/rules/no-constructed-context-value.md) | disallow passing constructed values to context providers |
| [react/no-create-ref](packages/eslint-plugin-react/src/rules/no-create-ref.md) | disallow `createRef` in function components |
| [react/no-dangerously-set-innerhtml](packages/eslint-plugin-react/src/rules/no-dangerously-set-innerhtml.md) | disallow when a DOM element is using both children and dangerouslySetInnerHTML' |
| [react/no-dangerously-set-innerhtml-with-children](packages/eslint-plugin-react/src/rules/no-dangerously-set-innerhtml-with-children.md) | disallow when a DOM element is using both children and dangerouslySetInnerHTML' |
| [react/no-namespace](packages/eslint-plugin-react/src/rules/no-namespace.md) | enforce that namespaces are not used in React elements |
| [react/no-string-refs](packages/eslint-plugin-react/src/rules/no-string-refs.md) | disallow using deprecated string refs |
| [react/no-string-style-props](packages/eslint-plugin-react/src/rules/no-string-style-props.md) | disallow using string as style props value |
| [react/no-unstable-default-props](packages/eslint-plugin-react/src/rules/no-unstable-default-props.md) | disallow usage of unstable value as default param in function component |
| [react/no-unstable-nested-components](packages/eslint-plugin-react/src/rules/no-unstable-nested-components.md) | disallow usage of unstable nested components |
| [react/prefer-destructuring-assignment](packages/eslint-plugin-react/src/rules/prefer-destructuring-assignment.md) | enforce using destructuring assignment in component props and context |
| Name                                             | Description | 🔧 |
| :--------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------ | :- |
| [react/no-children-in-void-dom-elements](packages/eslint-plugin-react/src/rules/no-children-in-void-dom-elements.md) | disallow passing children to void DOM elements | |
| [react/no-class-component](packages/eslint-plugin-react/src/rules/no-class-component.md) | enforce that there are no class components | |
| [react/no-clone-element](packages/eslint-plugin-react/src/rules/no-clone-element.md) | disallow `cloneElement` | |
| [react/no-constructed-context-value](packages/eslint-plugin-react/src/rules/no-constructed-context-value.md) | disallow passing constructed values to context providers | |
| [react/no-create-ref](packages/eslint-plugin-react/src/rules/no-create-ref.md) | disallow `createRef` in function components | |
| [react/no-dangerously-set-innerhtml](packages/eslint-plugin-react/src/rules/no-dangerously-set-innerhtml.md) | disallow when a DOM element is using both children and dangerouslySetInnerHTML' | |
| [react/no-dangerously-set-innerhtml-with-children](packages/eslint-plugin-react/src/rules/no-dangerously-set-innerhtml-with-children.md) | disallow when a DOM element is using both children and dangerouslySetInnerHTML' | |
| [react/no-namespace](packages/eslint-plugin-react/src/rules/no-namespace.md) | enforce that namespaces are not used in React elements | |
| [react/no-string-refs](packages/eslint-plugin-react/src/rules/no-string-refs.md) | disallow using deprecated string refs | |
| [react/no-string-style-props](packages/eslint-plugin-react/src/rules/no-string-style-props.md) | disallow using string as style props value | |
| [react/no-unstable-default-props](packages/eslint-plugin-react/src/rules/no-unstable-default-props.md) | disallow usage of unstable value as default param in function component | |
| [react/no-unstable-nested-components](packages/eslint-plugin-react/src/rules/no-unstable-nested-components.md) | disallow usage of unstable nested components | |
| [react/prefer-destructuring-assignment](packages/eslint-plugin-react/src/rules/prefer-destructuring-assignment.md) | enforce using destructuring assignment in component props and context | |

<!-- end auto-generated rules list -->

Expand All @@ -156,7 +159,7 @@ export default [
- [x] `jsx/no-script-url`
- [ ] `jsx/no-target-blank`
- [ ] `jsx/no-unknown-property`
- [ ] `jsx/no-useless-fragment`
- [x] `jsx/no-useless-fragment`
- [ ] `jsx/prefer-fragment-syntax`
- [x] `jsx/prefer-shorthand-boolean`
- [x] `naming-convention/filename-extension`
Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin-jsx/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import jsxNoLeakedConditionalRendering from "./rules/no-leaked-conditional-rende
import jsxNoMissingKey from "./rules/no-missing-key";
import jsxNoMisusedCommentInTextNode from "./rules/no-misused-comment-in-textnode";
import jsxNoScriptUrl from "./rules/no-script-url";
import jsxNoUselessFragment from "./rules/no-useless-fragment";
import jsxPreferShorthandJsxBoolean from "./rules/prefer-shorthand-boolean";

export { name } from "../package.json";
Expand All @@ -18,5 +19,6 @@ export const rules = {
"no-missing-key": jsxNoMissingKey,
"no-misused-comment-in-textnode": jsxNoMisusedCommentInTextNode,
"no-script-url": jsxNoScriptUrl,
"no-useless-fragment": jsxNoUselessFragment,
"prefer-shorthand-boolean": jsxPreferShorthandJsxBoolean,
} as const;
83 changes: 83 additions & 0 deletions packages/eslint-plugin-jsx/src/rules/no-useless-fragment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# jsx/no-useless-fragment

🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).

<!-- end auto-generated rule header -->

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a [keyed fragment](https://react.dev/reference/react/Fragment#caveats).

## Rule Details

### ❌ Incorrect

```tsx
<>{foo}</>

<><Foo /></>

<p><>foo</></p>

<></>

<Fragment>foo</Fragment>

<React.Fragment>foo</React.Fragment>

<section>
<>
<div />
<div />
</>
</section>

{showFullName ? <>{fullName}</> : <>{firstName}</>}
```

### ✅ Correct

```tsx
{foo}

<Foo />

<>
<Foo />
<Bar />
</>

<>foo {bar}</>

<> {foo}</>

const cat = <>meow</>

<SomeComponent>
<>
<div />
<div />
</>
</SomeComponent>

<Fragment key={item.id}>{item.value}</Fragment>

{showFullName ? fullName : firstName}
```

## Rule Options

### `allowExpressions`

When `true` single expressions in a fragment will be allowed. This is useful in
places like Typescript where `string` does not satisfy the expected return type
of `JSX.Element`. A common workaround is to wrap the variable holding a string
in a fragment and expression.

Examples of **correct** code for the rule, when `"allowExpressions"` is `true`:

```jsx
<>{foo}</>

<>
{foo}
</>
```
Loading