Skip to content

docs(linter/react): improve docs for jsx-curly-brace-presence#17579

Merged
graphite-app[bot] merged 1 commit intomainfrom
improve-curly-presence-rule
Jan 2, 2026
Merged

docs(linter/react): improve docs for jsx-curly-brace-presence#17579
graphite-app[bot] merged 1 commit intomainfrom
improve-curly-presence-rule

Conversation

@connorshea
Copy link
Member

For some reason, this rule was never updated to use the standard documentation format. The fields on the config struct were also not updated with doc comments, and so had no explanation. Now they do.

Generated docs:

### What it does

Disallow unnecessary JSX expressions when literals alone are
sufficient or enforce JSX expressions on literals in JSX children or
attributes.

This rule allows you to enforce curly braces or disallow unnecessary
curly braces in JSX props and/or children.

For situations where JSX expressions are unnecessary, please refer to
[the React doc](https://react.dev/learn/writing-markup-with-jsx)
and [this page about JSX
gotchas](https://github.com/facebook/react/blob/v15.4.0-rc.3/docs/docs/02.3-jsx-gotchas.md#html-entities).

### Why is this bad?

Using different styles for your JSX code can make it harder to read and
less consistent.

Code consistency improves readability. By enforcing or disallowing
curly braces in JSX props and/or children, this rule helps maintain
consistent patterns across your application.

### Rule Details

By default, this rule will check for and warn about unnecessary curly
braces in both JSX props and children. For the sake of backwards
compatibility, prop values that are JSX elements are not considered by
default.

You can pass in options to enforce the presence of curly braces on JSX
props, children, JSX prop values that are JSX elements, or any
combination of the three. The same options are available for not
allowing unnecessary curly braces as well as ignoring the check.

**Note**: it is _highly recommended_ that you configure this rule with
an object, and that you set "propElementValues" to "always". The ability
to omit curly braces around prop values that are JSX elements is
obscure, and intentionally undocumented, and should not be relied upon.

#### Example Configurations

```jsonc
{
  "rules": {
    "react/jsx-curly-brace-presence": ["error", { "props": <string>, "children": <string>, "propElementValues": <string> }]
  }
}
```

or alternatively

```jsonc
{
  "rules": {
    "react/jsx-curly-brace-presence": ["error", "always"], // or "never" or "ignore"
  },
}
```

### Fix Details

If passed in the option to fix, this is how a style violation will get fixed

- `always`: wrap a JSX attribute in curly braces/JSX expression and/or a JSX child the same way but also with double quotes
- `never`: get rid of curly braces from a JSX attribute and/or a JSX child

- All fixing operations use double quotes.

### Examples

Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always" }`:

```jsx
<App>Hello world</App>;
<App prop="Hello world">{"Hello world"}</App>;
```

They can be fixed to:

```jsx
<App>{"Hello world"}</App>;
<App prop={"Hello world"}>{"Hello world"}</App>;
```

Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never" }`:

```jsx
<App>{"Hello world"}</App>;
<App prop={"Hello world"} attr={"foo"} />;
```

They can be fixed to:

```jsx
<App>Hello world</App>;
<App prop="Hello world" attr="foo" />;
```

Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always", "propElementValues": "always" }`:

```jsx
<App prop=<div /> />
```

They can be fixed to:

```jsx
<App prop={<div />} />
```

Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never", "propElementValues": "never" }`:

```jsx
<App prop={<div />} />
```

They can be fixed to:

```jsx
<App prop=<div /> />
```

Examples of **incorrect** code for this rule, when configured with `"always"`:

```jsx
<App>Hello world</App>;
<App prop="Hello world" attr="foo">
  Hello world
</App>;
```

They can be fixed to:

```jsx
<App>{"Hello world"}</App>;
<App prop={"Hello world"} attr={"foo"}>
  {"Hello world"}
</App>;
```

Examples of **incorrect** code for this rule, when configured with `"never"`:

```jsx
<App prop={"foo"} attr={"bar"}>
  {"Hello world"}
</App>
```

It can fixed to:

```jsx
<App prop="foo" attr="bar">
  Hello world
</App>
```

### Edge cases

The fix also deals with template literals, strings with quotes, and
strings with escapes characters.

- If the rule is set to get rid of unnecessary curly braces and the
  template literal inside a JSX expression has no expression, it will
  throw a warning and be fixed with double quotes. For example:

```jsx
<App prop={`Hello world`}>{`Hello world`}</App>
```

will be warned and fixed to:

```jsx
<App prop="Hello world">Hello world</App>
```

- If the rule is set to enforce curly braces and the strings have
  quotes, it will be fixed with double quotes for JSX children and the
  normal way for JSX attributes. Also, double quotes will be escaped in
  the fix.

For example:

```jsx
<App prop='Hello "foo" world'>Hello 'foo' "bar" world</App>
```

will warned and fixed to:

```jsx
<App prop={'Hello "foo" world'}>{"Hello 'foo' \"bar\" world"}</App>
```

- If the rule is set to get rid of unnecessary curly braces(JSX
  expression) and there are characters that need to be escaped in its JSX
  form, such as quote characters, [forbidden JSX text
  characters](https://facebook.github.io/jsx/), escaped characters and
  anything that looks like HTML entity names, the code will not be warned
  because the fix may make the code less readable.

Examples of **correct** code for this rule, even when configured with `"never"`:

```jsx
<Color text={"\u00a0"} />
<App>{"Hello \u00b7 world"}</App>;
<style type="text/css">{'.main { margin-top: 0; }'}</style>;
/**
 * there's no way to inject a whitespace into jsx without a container so this
 * will always be allowed.
 */
<App>{' '}</App>
<App>{'     '}</App>
<App>{/* comment */ <Bpp />}</App> // the comment makes the container necessary
```

### When Not To Use It

You should turn this rule off if you are not concerned about maintaining
consistency regarding the use of curly braces in JSX props and/or
children as well as the use of unnecessary JSX expressions.

## Configuration

This rule accepts a configuration object with the following properties:

### children

type: `"always" | "never" | "ignore"`

default: `"never"`

Whether to enforce or disallow curly braces for child content of a JSX element.

- `never` will disallow unnecessary curly braces, e.g. this will be preferred: `<Foo>I love oxlint</Foo>`
- `always` will force the usage of curly braces like this, in all cases: `<Foo>{'I love oxlint'}</Foo>`
- `ignore` will allow either style for child content.

### propElementValues

type: `"always" | "never" | "ignore"`

default: `"ignore"`

When set to `ignore` or `never`, this JSX code is allowed (or enforced):
`<App prop=<div /> />;`

When set to `always`, the curly braces are required for prop values that are
JSX elements: `<App prop={<div />} />;`

**Note**: it is _highly_ recommended that you set `propElementValues` to `always`.
The ability to omit curly braces around prop values that are JSX elements is obscure, and
intentionally undocumented, and should not be relied upon.

### props

type: `"always" | "never" | "ignore"`

default: `"never"`

Whether to enforce or disallow curly braces for props on JSX elements.

- `never` will disallow unnecessary curly braces, e.g. this will be preferred: `<Foo foo="bar" />`
- `always` will force the usage of curly braces like this, in all cases: `<Foo foo={'bar'} />`
- `ignore` will allow either style for prop values.

Copilot AI review requested due to automatic review settings January 2, 2026 01:33
@connorshea connorshea requested a review from camc314 as a code owner January 2, 2026 01:33
@github-actions github-actions bot added the A-linter Area - Linter label Jan 2, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the documentation for the react/jsx-curly-brace-presence linter rule by migrating it to the standard documentation format and adding comprehensive field documentation.

Key Changes

  • Added detailed doc comments to the JsxCurlyBracePresence configuration struct fields (props, children, prop_element_values) explaining their behavior and valid values
  • Updated the rule documentation to follow the standard format with clear sections (What it does, Why is this bad, Rule Details, Examples, etc.)
  • Updated the React documentation link from the deprecated URL to the current react.dev domain
  • Normalized whitespace in test cases (replaced tabs with spaces)

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs Added comprehensive doc comments to config struct fields; standardized rule documentation format with improved sections and examples; updated React doc link; normalized test case whitespace
crates/oxc_linter/src/snapshots/react_jsx_curly_brace_presence.snap Updated snapshot to reflect column number changes resulting from test input whitespace normalization

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codspeed-hq
Copy link

codspeed-hq bot commented Jan 2, 2026

CodSpeed Performance Report

Merging #17579 will not alter performance

Comparing improve-curly-presence-rule (209ab7e) with main (bc7aae7)1

Summary

✅ 4 untouched
⏩ 41 skipped2

Footnotes

  1. No successful run was found on main (7005873) during the generation of this report, so bc7aae7 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 41 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@connorshea connorshea changed the title docs(linter): Improve documentation for react/jsx-curly-brace-presence rule. docs(linter): Improve documentation for react/jsx-curly-brace-presence rule. Jan 2, 2026
@github-actions github-actions bot added the C-docs Category - Documentation. Related to user-facing or internal documentation label Jan 2, 2026
@camc314 camc314 changed the title docs(linter): Improve documentation for react/jsx-curly-brace-presence rule. docs(linter/react): improve docs for jsx-curly-brace-presence Jan 2, 2026
@camc314 camc314 self-assigned this Jan 2, 2026
@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label Jan 2, 2026
Copy link
Contributor

camc314 commented Jan 2, 2026

Merge activity

For some reason, this rule was never updated to use the standard documentation format. The fields on the config struct were also not updated with doc comments, and so had no explanation. Now they do.

Generated docs:

````md
### What it does

Disallow unnecessary JSX expressions when literals alone are
sufficient or enforce JSX expressions on literals in JSX children or
attributes.

This rule allows you to enforce curly braces or disallow unnecessary
curly braces in JSX props and/or children.

For situations where JSX expressions are unnecessary, please refer to
[the React doc](https://react.dev/learn/writing-markup-with-jsx)
and [this page about JSX
gotchas](https://github.com/facebook/react/blob/v15.4.0-rc.3/docs/docs/02.3-jsx-gotchas.md#html-entities).

### Why is this bad?

Using different styles for your JSX code can make it harder to read and
less consistent.

Code consistency improves readability. By enforcing or disallowing
curly braces in JSX props and/or children, this rule helps maintain
consistent patterns across your application.

### Rule Details

By default, this rule will check for and warn about unnecessary curly
braces in both JSX props and children. For the sake of backwards
compatibility, prop values that are JSX elements are not considered by
default.

You can pass in options to enforce the presence of curly braces on JSX
props, children, JSX prop values that are JSX elements, or any
combination of the three. The same options are available for not
allowing unnecessary curly braces as well as ignoring the check.

**Note**: it is _highly recommended_ that you configure this rule with
an object, and that you set "propElementValues" to "always". The ability
to omit curly braces around prop values that are JSX elements is
obscure, and intentionally undocumented, and should not be relied upon.

#### Example Configurations

```jsonc
{
  "rules": {
    "react/jsx-curly-brace-presence": ["error", { "props": <string>, "children": <string>, "propElementValues": <string> }]
  }
}
```

or alternatively

```jsonc
{
  "rules": {
    "react/jsx-curly-brace-presence": ["error", "always"], // or "never" or "ignore"
  },
}
```

### Fix Details

If passed in the option to fix, this is how a style violation will get fixed

- `always`: wrap a JSX attribute in curly braces/JSX expression and/or a JSX child the same way but also with double quotes
- `never`: get rid of curly braces from a JSX attribute and/or a JSX child

- All fixing operations use double quotes.

### Examples

Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always" }`:

```jsx
<App>Hello world</App>;
<App prop="Hello world">{"Hello world"}</App>;
```

They can be fixed to:

```jsx
<App>{"Hello world"}</App>;
<App prop={"Hello world"}>{"Hello world"}</App>;
```

Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never" }`:

```jsx
<App>{"Hello world"}</App>;
<App prop={"Hello world"} attr={"foo"} />;
```

They can be fixed to:

```jsx
<App>Hello world</App>;
<App prop="Hello world" attr="foo" />;
```

Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always", "propElementValues": "always" }`:

```jsx
<App prop=<div /> />
```

They can be fixed to:

```jsx
<App prop={<div />} />
```

Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never", "propElementValues": "never" }`:

```jsx
<App prop={<div />} />
```

They can be fixed to:

```jsx
<App prop=<div /> />
```

Examples of **incorrect** code for this rule, when configured with `"always"`:

```jsx
<App>Hello world</App>;
<App prop="Hello world" attr="foo">
  Hello world
</App>;
```

They can be fixed to:

```jsx
<App>{"Hello world"}</App>;
<App prop={"Hello world"} attr={"foo"}>
  {"Hello world"}
</App>;
```

Examples of **incorrect** code for this rule, when configured with `"never"`:

```jsx
<App prop={"foo"} attr={"bar"}>
  {"Hello world"}
</App>
```

It can fixed to:

```jsx
<App prop="foo" attr="bar">
  Hello world
</App>
```

### Edge cases

The fix also deals with template literals, strings with quotes, and
strings with escapes characters.

- If the rule is set to get rid of unnecessary curly braces and the
  template literal inside a JSX expression has no expression, it will
  throw a warning and be fixed with double quotes. For example:

```jsx
<App prop={`Hello world`}>{`Hello world`}</App>
```

will be warned and fixed to:

```jsx
<App prop="Hello world">Hello world</App>
```

- If the rule is set to enforce curly braces and the strings have
  quotes, it will be fixed with double quotes for JSX children and the
  normal way for JSX attributes. Also, double quotes will be escaped in
  the fix.

For example:

```jsx
<App prop='Hello "foo" world'>Hello 'foo' "bar" world</App>
```

will warned and fixed to:

```jsx
<App prop={'Hello "foo" world'}>{"Hello 'foo' \"bar\" world"}</App>
```

- If the rule is set to get rid of unnecessary curly braces(JSX
  expression) and there are characters that need to be escaped in its JSX
  form, such as quote characters, [forbidden JSX text
  characters](https://facebook.github.io/jsx/), escaped characters and
  anything that looks like HTML entity names, the code will not be warned
  because the fix may make the code less readable.

Examples of **correct** code for this rule, even when configured with `"never"`:

```jsx
<Color text={"\u00a0"} />
<App>{"Hello \u00b7 world"}</App>;
<style type="text/css">{'.main { margin-top: 0; }'}</style>;
/**
 * there's no way to inject a whitespace into jsx without a container so this
 * will always be allowed.
 */
<App>{' '}</App>
<App>{'     '}</App>
<App>{/* comment */ <Bpp />}</App> // the comment makes the container necessary
```

### When Not To Use It

You should turn this rule off if you are not concerned about maintaining
consistency regarding the use of curly braces in JSX props and/or
children as well as the use of unnecessary JSX expressions.

## Configuration

This rule accepts a configuration object with the following properties:

### children

type: `"always" | "never" | "ignore"`

default: `"never"`

Whether to enforce or disallow curly braces for child content of a JSX element.

- `never` will disallow unnecessary curly braces, e.g. this will be preferred: `<Foo>I love oxlint</Foo>`
- `always` will force the usage of curly braces like this, in all cases: `<Foo>{'I love oxlint'}</Foo>`
- `ignore` will allow either style for child content.

### propElementValues

type: `"always" | "never" | "ignore"`

default: `"ignore"`

When set to `ignore` or `never`, this JSX code is allowed (or enforced):
`<App prop=<div /> />;`

When set to `always`, the curly braces are required for prop values that are
JSX elements: `<App prop={<div />} />;`

**Note**: it is _highly_ recommended that you set `propElementValues` to `always`.
The ability to omit curly braces around prop values that are JSX elements is obscure, and
intentionally undocumented, and should not be relied upon.

### props

type: `"always" | "never" | "ignore"`

default: `"never"`

Whether to enforce or disallow curly braces for props on JSX elements.

- `never` will disallow unnecessary curly braces, e.g. this will be preferred: `<Foo foo="bar" />`
- `always` will force the usage of curly braces like this, in all cases: `<Foo foo={'bar'} />`
- `ignore` will allow either style for prop values.
````
@graphite-app graphite-app bot force-pushed the improve-curly-presence-rule branch from 209ab7e to 884fb63 Compare January 2, 2026 12:44
@graphite-app graphite-app bot merged commit 884fb63 into main Jan 2, 2026
20 checks passed
@graphite-app graphite-app bot deleted the improve-curly-presence-rule branch January 2, 2026 12:49
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Jan 2, 2026
graphite-app bot pushed a commit that referenced this pull request Jan 5, 2026
# Oxlint
### 💥 BREAKING CHANGES

- f7da875 oxlint: [**BREAKING**] Remove oxc_language_server binary (#17457) (Boshen)

### 🚀 Features

- 659c23e linter: Init note field boilerplate  (#17589) (Shrey Sudhir)
- 6870b64 parser: Add TS1363 error code (#17609) (Sysix)
- 6154c8c linter/eslint-plugin-vitest: Implemented vitest/warn-todo rule (#17228) (Said Atrahouch)
- 0043cd6 linter/eslint-plugin-vitest: Implement consistent-vitest-vi rule (#17389) (Said Atrahouch)
- a6d773d linter: Add full TS support to eslint/no-useless-constructor (#17592) (camc314)
- f02c0e7 linter/eslint: Implement complexity (#17569) (Nguyen Tran)
- bc7aae7 linter/no-unused-vars: Add fixer to remove unused catch bindings (#17567) (Don Isaac)
- 9e8ec78 linter/only-throw-error rule: Add `allowRethrowing` option for  (#17554) (camc314)
- b67e819 linter: Add fixer for `unicorn/prefer-response-static-json` rule (#17559) (Mikhail Baev)
- 44b0361 linter/vue: Implement no-this-in-before-route-enter (#17525) (yefan)
- ee34716 linter/react: Implement no-will-update-set-state (#17530) (Kenzo Wada)
- 3088e1d linter/react: Implement no-this-in-sfc (#17535) (Kenzo Wada)
- 29a2868 linter/jsx-a11y: Implement no-static-element-interactions (#17538) (Kenzo Wada)
- eadf057 linter: Enable tsconfig auto discovery by default (#17489) (Boshen)
- 12a7d6e website_linter: Add a count of rules with fixes available to rules table. (#17476) (Connor Shea)

### 🐛 Bug Fixes

- a702f13 oxlint/lsp: Correct position for "disable for this file" with shebang (#17613) (Sysix)
- 19fdfb6 linter: Panic in `sort-keys` rule with Unicode numeric characters (#17629) (Adel Rodríguez)
- 2e8f469 vscode: Search for `node_modules/.bin/oxlint.exe` too (bun setup) (#17597) (Sysix)
- be39906 linter/aria-proptypes: Allow template literals with expressions for string-type ARIA props (#17460) (Jökull Sólberg Auðunsson)
- 529901c linter: Include JS plugin rules when calculating total rule count (#17520) (connorshea)
- 96ef2cc linter: Print total rule # when using a single nested config (#17517) (connorshea)
- 9ad0f29 oxlint: Do not enable external plugin store when no external linter is passed (#17498) (Sysix)
- 174375d oxfmt,oxlint: Disable mimalloc for 32-bit Arm targets (#17473) (Yaksh Bariya)
- ff70fe9 linter/no-standalone-expect: Allows expect in wrapper functions passed to test blocks (#17427) (Copilot)
- dab232f linter/catch-or-return: Handle arrow functions with implicit returns correctly (#17440) (Copilot)
- a38892a linter: Update no-unnecessary-template-expression docs and test case (#17453) (camc314)

### ⚡ Performance

- 605dbf1 vscode: Restrict searching for oxlint/oxfmt binaries only 3 levels deep + 10s timeout (#17345) (Sysix)

### 📚 Documentation

- 884fb63 linter/react: Improve docs for jsx-curly-brace-presence (#17579) (connorshea)
- 1d3ee07 linter: Improve rule explanation for `vue/no-this-in-before-route-enter`. (#17581) (connorshea)
- 5f189f8 linter/arrow-body-style: Correctly document default mode option (#17566) (Rägnar O'ock)
- bb2e8e4 linter: Add a note to the `typescript/no-var-requires` rule about the missing `allow` option (#17551) (connorshea)
- 655afc1 linter: Improve docs for `import/extensions` and add a few more tests (#17539) (connorshea)
- 7e5fc90 linter: Update list of plugins that are reserved. (#17516) (connorshea)
# Oxfmt
### 💥 BREAKING CHANGES

- f7da875 oxlint: [**BREAKING**] Remove oxc_language_server binary (#17457) (Boshen)

### 🚀 Features

- 8fd4ea9 oxfmt: `options.embeddedLanguageFormatting` is now `"auto"` by default (#17649) (leaysgur)

### 🐛 Bug Fixes

- c9b5d7d formatter/sort_imports: Handle alignable_comment correctly (#17646) (leaysgur)
- 453222d formatter: Missing comment handling for end-of-line comments in member chains (#17659) (Dunqing)
- 0805ff2 formatter: Incorrect inline comment placement in try-catch (#17657) (Dunqing)
- 3a0c782 formatter: Don't move comments into optional call parentheses (#17582) (magic-akari)
- 174375d oxfmt,oxlint: Disable mimalloc for 32-bit Arm targets (#17473) (Yaksh Bariya)

### ⚡ Performance

- abb28dc oxfmt: Turn of pretty print from sort-package-json (#17452) (Boshen)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-docs Category - Documentation. Related to user-facing or internal documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants