useBetterDomTraversing (JavaScript)
Language JavaScript (and super languages)
Summary
Section titled “Summary”- Diagnostic Category:
lint/nursery/useBetterDomTraversing - This rule has an unsafe fix.
- The default severity of this rule is information.
- Sources:
- Inspired from
unicorn/better-dom-traversing
- Inspired from
How to configure
Section titled “How to configure”{ "linter": { "rules": { "nursery": { "useBetterDomTraversing": "error" } } }}Description
Section titled “Description”Prefer modern DOM traversal APIs over positional indexes and chained walks.
Named first-child accessors, querySelector(), and closest() describe intent more clearly
than childNodes[0], children[n], and repeated .parentElement access.
Merging chained .querySelector() calls with static selectors has the same benefit.
Fixes are unsafe because the replacement is not always equivalent:
.childNodes[0]isundefinedwhen empty;.firstChildisnull.closest()looks for any matching ancestor, not an exact number of.parentElementhops- chained
.querySelector()calls search inside the first match, while a combined selector searches from the original node
props.children is ignored because that is component data, not DOM traversal.
Examples
Section titled “Examples”Invalid
Section titled “Invalid”element.childNodes[0];code-block.js:1:1 lint/nursery/useBetterDomTraversing FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This indexes .childNodes to get the first child.
> 1 │ element.childNodes[0];
│ ^^^^^^^^^^^^^^^^^^^^^
2 │
ℹ A positional index is harder to read than a named first-child accessor.
ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.
ℹ Unsafe fix: Use .firstChild instead.
1 │ - element.childNodes[0];
1 │ + element.firstChild;
2 2 │
element.children[0];code-block.js:1:1 lint/nursery/useBetterDomTraversing FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This indexes .children to get the first element child.
> 1 │ element.children[0];
│ ^^^^^^^^^^^^^^^^^^^
2 │
ℹ A positional index is harder to read than a named first-child accessor.
ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.
ℹ Unsafe fix: Use .firstElementChild instead.
1 │ - element.children[0];
1 │ + element.firstElementChild;
2 2 │
element.children[2];code-block.js:1:1 lint/nursery/useBetterDomTraversing ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This uses a positional index on .children.
> 1 │ element.children[2];
│ ^^^^^^^^^^^^^^^^^^^
2 │
ℹ A CSS selector describes which child you want without relying on a numeric index.
ℹ Replace this with .querySelector() and a selector for the child.
ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.
element.parentElement.parentElement;code-block.js:1:1 lint/nursery/useBetterDomTraversing ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ This walks ancestors by chaining .parentElement.
> 1 │ element.parentElement.parentElement;
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │
ℹ .closest() looks up a matching ancestor without repeating .parentElement.
ℹ Replace this chain with .closest() and a selector for the ancestor.
ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.
element.querySelector("a").querySelector("b");code-block.js:1:1 lint/nursery/useBetterDomTraversing FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ These .querySelector() calls are chained.
> 1 │ element.querySelector("a").querySelector("b");
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │
ℹ One .querySelector() call with a combined selector is easier to read.
ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.
ℹ Unsafe fix: Merge the .querySelector() calls.
1 │ - element.querySelector("a").querySelector("b");
1 │ + element.querySelector(":scope·a·b");
2 2 │
element.firstChild;element.firstElementChild;element.querySelector("li");element.closest("form");const child = props.children[0];Related links
Section titled “Related links”Copyright (c) 2023-present Biome Developers and Contributors.