packages/docs/src/routes/docs/(qwik)/advanced/eslint/index.mdx
import './styles.css';
<div> <h1 id="smth">ESLint-Rules</h1> <p>Qwik comes with its own set of ESLint rules to help developers write better code.</p> <div class="ruleset-legend panel"> <div class="panel-border"> <span class="icon icon-inactive">✅</span> <b>Warn</b> in 'recommended' ruleset </div> <div class="panel-border"> <span class="icon">✅</span> <b>Error</b> in 'recommended' ruleset </div> <div class="panel-border"> <span class="icon icon-inactive">🔔</span> <b>Warn</b> in 'strict' ruleset </div> <div class="list-none my-6 px-6"> <span class="icon">🔔</span> <b>Error</b> in 'strict' ruleset </div> </div> <h2>Possible Problems</h2> <p>These rules are available.</p> <div class="my-6"><a href="#use-method-usage" class="p-4 flex panel">
<div class="flex-1">
<code>use-method-usage</code>
<span class="rule-description">Detect invalid use of use hooks.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#valid-lexical-scope" class="p-4 flex panel">
<div class="flex-1">
<code>valid-lexical-scope</code>
<span class="rule-description">Used the tsc typechecker to detect the capture of unserializable data in dollar ($) scopes.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#loader-location" class="p-4 flex panel">
<div class="flex-1">
<code>loader-location</code>
<span class="rule-description">Detect declaration location of loader$.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': true,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#no-react-props" class="p-4 flex panel">
<div class="flex-1">
<code>no-react-props</code>
<span class="rule-description">Disallow usage of React-specific `className`/`htmlFor` props.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#prefer-classlist" class="p-4 flex panel">
<div class="flex-1">
<code>prefer-classlist</code>
<span class="rule-description">Enforce using the classlist prop over importing a classnames helper. The classlist prop accepts an object `{ [class: string]: boolean }` just like classnames.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': true,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#jsx-no-script-url" class="p-4 flex panel">
<div class="flex-1">
<code>jsx-no-script-url</code>
<span class="rule-description">Disallow javascript: URLs.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': true,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#jsx-key" class="p-4 flex panel">
<div class="flex-1">
<code>jsx-key</code>
<span class="rule-description">Disallow missing `key` props in iterators/collection literals</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': true,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#unused-server" class="p-4 flex panel">
<div class="flex-1">
<code>unused-server</code>
<span class="rule-description">Detect unused server$() functions.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#jsx-img" class="p-4 flex panel">
<div class="flex-1">
<code>jsx-img</code>
<span class="rule-description">For performance reasons, always provide width and height attributes for <img> elements, it will help to prevent layout shifts.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': true,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#jsx-a" class="p-4 flex panel">
<div class="flex-1">
<code>jsx-a</code>
<span class="rule-description">For a perfect SEO score, always provide href attribute for <a> elements.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': true,
}}
>
✅
</span>
<span
class={{
'icon': false,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<a href="#no-use-visible-task" class="p-4 flex panel">
<div class="flex-1">
<code>no-use-visible-task</code>
<span class="rule-description">Detect useVisibleTask$() functions.</span>
</div>
<div class="flex gap-2 items-center">
<span
class={{
'icon': false,
'icon icon-inactive': true,
}}
>
✅
</span>
<span
class={{
'icon': true,
'icon icon-inactive': false,
}}
>
🔔
</span>
</div>
</a>
<div class="rule-wrapper">
<h3 id="use-method-usage">use-method-usage</h3>
<span>Detect invalid use of use hooks.</span>
</div>
<div class="rule-wrapper">
<h3 id="valid-lexical-scope">valid-lexical-scope</h3>
<span>Used the tsc typechecker to detect the capture of unserializable data in dollar ($) scopes.</span>
export const HelloWorld = component$(() => { const print = $((msg: string) => { console.log(msg); });
useTask$(() => { print("Hello World"); });
return <h1>Hello</h1>; });
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {1,4} /print/#a /(msg: string)/#b)
import { component$, useTask$ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
const print = (msg: string) => {
console.log(msg);
};
useTask$(() => {
print("Hello World");
});
return <h1>Hello</h1>;
});
export const HelloWorld = component$(() => { const click = $(() => console.log()); return ( <button onClick$={click}>log it</button> ); });
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {1} /click/#a
import { component$ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
const click = () => console.log();
return (
<button onClick$={click}>log it</button>
);
});
export const HelloWorld = component$(() => { const person = { name: 'Bob' };
return ( <button onClick$={() => { person.name = 'Alice'; }}> {person.name} </button> ); });
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {4} /personName/#a
import { component$ } from '@builder.io/qwik';
export const HelloWorld = component$(() => {
let personName = 'Bob';
return (
<button onClick$={() => {
personName = 'Alice';
}}>
{personName}
</button>
);
});
</div>
<div class="rule-wrapper">
<h3 id="loader-location">loader-location</h3>
<span>Detect declaration location of loader$.</span>
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(https://.../products/${requestEvent.params.productId});
const product = await res.json();
return product as Product;
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {3} /routeLoader$/#a title="src/components/product/product.tsx"
import { routeLoader$ } from '@builder.io/qwik-city';
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(https://.../products/${requestEvent.params.productId});
const product = await res.json();
return product as Product;
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {3}
import { routeLoader$ } from '@builder.io/qwik-city';
const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(https://.../products/${requestEvent.params.productId});
const product = await res.json();
return product as Product;
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {3} /get/#a
import { routeLoader$ } from '@builder.io/qwik-city';
export const getProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
});
export const useProductDetails = routeLoader$(async (requestEvent) => {
const res = await fetch(https://.../products/${requestEvent.params.productId});
const product = await res.json();
return product as Product;
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {9} /fetcher/#a
import { routeLoader$ } from '@builder.io/qwik-city';
async function fetcher() {
const res = await fetch(`https://.../products/${requestEvent.params.productId}`);
const product = await res.json();
return product as Product;
}
export const useProductDetails = routeLoader$(fetcher);
</div>
<div class="rule-wrapper">
<h3 id="no-react-props">no-react-props</h3>
<span>Disallow usage of React-specific `className`/`htmlFor` props.</span>
</div>
<div class="rule-wrapper">
<h3 id="prefer-classlist">prefer-classlist</h3>
<span>Enforce using the classlist prop over importing a classnames helper. The classlist prop accepts an object `{ [class: string]: boolean }` just like classnames.</span>
export default component$((props) => { // Array syntax example return <div class={[ styles.container, 'p-8', props.isHighAttention ? 'text-green-500' : 'text-slate-500', { active: true} ]}>Hello world</div>;
// Object syntax example
return <div class={{
'text-green-500': props.isHighAttention,
'p-4': true
}}>Hello world</div>;
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {2,7-13} /classnames/#a
import { component$ } from '@builder.io/qwik';
import classnames from 'classnames';
import styles from './MyComponent.module.css';
export default component$((props) => {
return <div class={classnames(
styles.container,
'p-8',
{
'text-green-500' : props.isHighAttention,
'text-slate-500' : !props.isHighAttention,
},
{ active: true}
)}>Hello world</div>;
});
</div>
<div class="rule-wrapper">
<h3 id="jsx-no-script-url">jsx-no-script-url</h3>
<span>Disallow javascript: URLs.</span>
</div>
<div class="rule-wrapper">
<h3 id="jsx-key">jsx-key</h3>
<span>Disallow missing `key` props in iterators/collection literals</span>
export const Person = component$(() => { const person = { firstName: 'John', lastName: 'Doe', age: 32, }
return (
<ul>
{Object.keys(person).map((color) => (
<li key={person-${key}}>{person[key]}</li>
)}
</ul>
);
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {13}
import { component$ } from '@builder.io/qwik';
export const Person = component$(() => {
const person = {
firstName: 'John',
lastName: 'Doe',
age: 32,
}
return (
<ul>
{Object.keys(person).map((color) => (
<li>{person[key]}</li>
)}
</ul>
);
});
export const Person = component$(() => { const person = { firstName: 'John', lastName: 'Doe', age: 32, }
return (
{Object.keys(person).map((color) => (
<Fragment key={person-${key}}>
<Card value={person[key]} />
<Summary value={person[key]} />
</Fragment>
)}
);
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {14}
import { component$ } from '@builder.io/qwik';
import Card from './Card';
import Summary from './Summary';
export const Person = component$(() => {
const person = {
firstName: 'John',
lastName: 'Doe',
age: 32,
}
return (
{Object.keys(person).map((color) => (
< key={`person-${key}`}>
<Card value={person[key]} />
<Summary value={person[key]} />
</>
)}
);
});
export const ColorList = component$(() => { const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li key={color-${color}}>{color}</li>
)}
</ul>
);
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {9}
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li>{color}</li>
)}
</ul>
);
});
export const ColorList = component$(() => { const colors = ['red', 'green', 'blue'];
return (
{colors.map((color) => (
<Fragment key={color-${color}}>
<h2>{color}</h2>
<p>The color "${color}" is a great color.</p>
</Fragment>
)}
);
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {8,11}
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
{colors.map((color) => (
< key={`color-${color}`}>
<h2>{color}</h2>
<p>The color "${color}" is a great color.</p>
</>
)}
);
});
export const ColorList = component$(() => { const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li key={color-${color}}>{color}</li>
)}
</ul>
);
});
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {9} /key=/#a /not-a-good-idea/#b
import { component$ } from '@builder.io/qwik';
export const ColorList = component$(() => {
const colors = ['red', 'green', 'blue'];
return (
<ul>
{colors.map((color) => (
<li key="not-a-good-idea">{color}</li>
)}
</ul>
);
});
</div>
<div class="rule-wrapper">
<h3 id="unused-server">unused-server</h3>
<span>Detect unused server$() functions.</span>
const serverGreeter = server$((firstName: string, lastName: string) => {
const greeting = Hello ${firstName} ${lastName};
return greeting;
});
export default component$(() => ( <button onClick$={$(async () => { const greeting = await serverGreeter('John', 'Doe'); alert(greeting); })} > greet </button> ); );
</div>
<p>Examples of <b>incorrect</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge bad">✕</span>
```tsx {4,12} /serverGreeter/#a
import { component$ } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
const serverGreeter = server$((firstName: string, lastName: string) => {
const greeting = `Hello ${firstName} ${lastName}`;
return greeting;
});
export default component$(() => (
<button
onClick$={async () => {
const greeting = 'not using the server$ function';
alert(greeting);
}}
>
greet
</button>
);
);
</div>
<div class="rule-wrapper">
<h3 id="jsx-img">jsx-img</h3>
<span>For performance reasons, always provide width and height attributes for <img> elements, it will help to prevent layout shifts.</span>
<p class="code-description">Serving images from public are not optimized, nor cached. Import images using ESM instead.</p>
</div>
<div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxImg.ts" target="_blank" class="edit-btn">Edit examples</a></div>
<h4>noWidthHeight</h4>
<p>Examples of <b>correct</b> code for this rule:</p>
<div class="code-wrapper">
<span class="badge good">✓</span>
```tsx /width/#a /height/#b
<p class="code-description">For performance reasons, always provide width and height attributes for `` elements, it will help to prevent layout shifts.</p>
</div>
<div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxImg.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>
<div class="rule-wrapper">
<h3 id="jsx-a">jsx-a</h3>
<span>For a perfect SEO score, always provide href attribute for <a> elements.</span>
<h4>noHref</h4>
<div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxA.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>
<div class="rule-wrapper">
<h3 id="no-use-visible-task">no-use-visible-task</h3>
<span>Detect useVisibleTask$() functions.</span>
<h4>noUseVisibleTask</h4>
<div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/noUseVisibleTask.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>
</div>
</div>