bun/jsx-no-forbidden-nesting
Disallow a JSX element inside another element that cannot contain it
HTML doesn't allow a link or a button inside another link or button. Browsers disagree about what a click on the inner element does. In server-rendered HTML, the parser ends an a or a button where the next one starts and ignores a form inside a form, so the DOM doesn't match your JSX.
The inner element is reported at any depth, not only as a direct child. By default the rule knows these pairs:
| Outer | Cannot contain |
|---|---|
a | a, button |
button | a, button |
form | form |
label | label |
Only the tag names are compared, so a Link component that renders an a doesn't count as an a.
Configure#
Off by default. To turn it on:
[lint.rules]
"bun/jsx-no-forbidden-nesting" = "error" # or "warn"Every option, set to its default. The ones that are commented out are unset by default.
[lint.rules]
"bun/jsx-no-forbidden-nesting" = ["error", {
# pairs = <list of objects>,
}]Examples#
const card = (
<a href={post.url}>
<h2>{post.title}</h2>
<button<button> cannot be inside <a>. onClick={save}>Save</button>
</a>
);const card = (
<article>
<a href={post.url}>
<h2>{post.title}</h2>
</a>
<button onClick={save}>Save</button>
</article>
);Options#
| Option | Default | What it does |
|---|---|---|
pairs | The table above | A list of { outer, inner } names. It replaces the default list. |
Use it for your own components:
[lint.rules]
"bun/jsx-no-forbidden-nesting" = ["error", {
pairs = [{ outer = "Link", inner = "Button" }],
}]{ "pairs": [{ "outer": "Link", "inner": "Button" }] }1 problemconst row = (
<Link to="/settings">
<Button<Button> cannot be inside <Link>.>Settings</Button>
</Link>
);Then the default pairs no longer apply. Add them to the list if you want to keep them:
{ "pairs": [{ "outer": "Link", "inner": "Button" }] }No problemsconst row = (
<a href="/settings">
<button>Settings</button>
</a>
);