Back to Qwik

Index

packages/docs/src/routes/docs/(qwik)/advanced/eslint/index.mdx

1.7.131.3 KB
Original Source

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 &lt;img&gt; 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 &lt;a&gt; 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> <h2>Details</h2> <div class="my-6">
<div class="rule-wrapper">
  <h3 id="use-method-usage">use-method-usage</h3>
  <span>Detect invalid use of use hooks.</span>
<h4>useWrongFunction</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {2} /component$/#a export const Counter = component$(() => { const count = useSignal(0); }); ``` </div> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {2} /component$/#a export const useCounter = () => { const count = useSignal(0); return count; }; ``` </div> <p>Examples of <b>incorrect</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge bad">✕</span> ```tsx {2} /component$/#a export const Counter = (() => { const count = useSignal(0); }); ``` <p class="code-description">`use*` methods can only be used in `component$` functions or inside `use*` hooks (e.g. `useCounter`).</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/useMethodUsage.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</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>
<h4>referencesOutside</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</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>; });

</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>;
});
<p class="code-description">Since Expressions are not serializable, they must be wrapped with `$( ... )` so that the optimizer can split the code into small chunks.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/validLexicalScope.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>invalidJsxDollar</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</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> ); });

</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>
  );
});
<p class="code-description">Event handler must be wrapped with `${ ... }`.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/validLexicalScope.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>mutableIdentifier</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {4} /person/#a import { component$ } from '@builder.io/qwik';

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>
  );
});
<p class="code-description">Simple values are not allowed to be mutated. Use an Object instead and edit one of its property.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/validLexicalScope.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>


<div class="rule-wrapper">
  <h3 id="loader-location">loader-location</h3>
  <span>Detect declaration location of loader$.</span>
<h4>invalidLoaderLocation</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {3} /routeLoader$/#a title="src/routes/product/[productId]/index.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; });

</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;
});
<p class="code-description">This is not a valid location for a route loader. It only can be used inside the `src/routes` folder, in a `layout.tsx` or `index.tsx` file.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/loaderLocation.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>missingExport</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {3} /export/#a 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; });

</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;
});
<p class="code-description">The route loader function must be exported.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/loaderLocation.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>wrongName</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {3} /use/#a 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; });

</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;
});
<p class="code-description">The route loader function name must start with `use`.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/loaderLocation.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>recommendedValue</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {3} /=>/#a 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; });

</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);
<p class="code-description">It is recommended to inline the arrow function. This will help the optimizer make sure that no server code is leaked to the client build.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/loaderLocation.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>


<div class="rule-wrapper">
  <h3 id="no-react-props">no-react-props</h3>
  <span>Disallow usage of React-specific `className`/`htmlFor` props.</span>
<h4>prefer</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx /class/#a /for/#b <MyReactComponent class="foo" for="#password" />; ``` </div> <p>Examples of <b>incorrect</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge bad">✕</span> ```tsx /className/#a /htmlFor/#b <MyReactComponent className="foo" htmlFor="#password" />; ``` <p class="code-description">Prefer `class` and `for` props over `className` and `htmlFor`.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/noReactProps.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</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>
<h4>preferClasslist</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {7-10,15,16} /class/#a import { component$ } from '@builder.io/qwik'; import styles from './MyComponent.module.css';

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>;
});
<p class="code-description">The class prop should be used instead of any 3rd party lib to efficiently set classes based on an object.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/preferClasslist.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>


<div class="rule-wrapper">
  <h3 id="jsx-no-script-url">jsx-no-script-url</h3>
  <span>Disallow javascript: URLs.</span>
<h4>noJSURL</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx <button onClick$={() => alert('open the door please')>ring</button> ``` </div> <p>Examples of <b>incorrect</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge bad">✕</span> ```tsx /javascript:/#a <button onClick$="javascript:alert('open the door please')">ring</button> ``` </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxNoScriptUrl.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>


<div class="rule-wrapper">
  <h3 id="jsx-key">jsx-key</h3>
  <span>Disallow missing `key` props in iterators/collection literals</span>
<h4>missingIterKey</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {13} /key=/#a 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 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>
  );
});
<p class="code-description">Missing `key` prop for element in iterator.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxKey.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>missingIterKeyUsePrag</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {14} /Fragment/#a 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) => ( <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]} />
      </>
    )}
  );
});
<p class="code-description">Missing `key` prop for element in iterator. The key prop allows for improved rendering performance. Shorthand fragment syntax does not support providing keys. Use `<Fragment>` instead</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxKey.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>missingArrayKey</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {9} /key=/#a import { component$ } from '@builder.io/qwik';

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>
  );
});
<p class="code-description">Missing `key` prop for element in array. The key prop allows for improved rendering performance.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxKey.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>missingArrayKeyUsePrag</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {8,11} /Fragment/#a import { component$, Fragment } from '@builder.io/qwik';

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>
      </>
    )}
  );
});
<p class="code-description">Missing `key` prop for element in array. The key prop allows for improved rendering performance. Shorthand fragment syntax does not support providing keys. Use `<Fragment>` instead</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxKey.ts" target="_blank" class="edit-btn">Edit examples</a></div> <h4>nonUniqueKeys</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx {9} /key=/#a import { component$ } from '@builder.io/qwik';

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>
  );
});
<p class="code-description">The `key` prop must be unique.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/jsxKey.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>


<div class="rule-wrapper">
  <h3 id="unused-server">unused-server</h3>
  <span>Detect unused server$() functions.</span>
<h4>unusedServer</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</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 = 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>
  );
);
<p class="code-description">A `server$` function is declared, but never used.</p> </div> <div class="edit-examples-wrapper"><a href="https://github.com/QwikDev/qwik/edit/main/packages/eslint-plugin-qwik/src/unusedServer.ts" target="_blank" class="edit-btn">Edit examples</a></div>
</div>


<div class="rule-wrapper">
  <h3 id="jsx-img">jsx-img</h3>
  <span>For performance reasons, always provide width and height attributes for &lt;img&gt; elements, it will help to prevent layout shifts.</span>
<h4>noLocalSrc</h4> <p>Examples of <b>correct</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge good">✓</span> ```tsx import Image from '~/media/image.png'; <Image /> ``` </div> <p>Examples of <b>incorrect</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge bad">✕</span> ```tsx
<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

</div> <p>Examples of <b>incorrect</b> code for this rule:</p> <div class="code-wrapper"> <span class="badge bad">✕</span> ```tsx
<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 &lt;a&gt; 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>