ESLintルール

Qwikには、開発者がより良いコードを作成するための独自のESLintルールセットが付属しています。

警告(推奨ルールセット)

エラー(推奨ルールセット)

🔔 警告(厳格ルールセット)

🔔 エラー(厳格ルールセット)

考えられる問題

これらのルールが利用可能です。

詳細

use-method-usage

useフックの無効な使用を検出します。

useWrongFunction

このルールの正しいコードの例

export const Counter = component$(() => {
  const count = useSignal(0);
});
export const useCounter = () => {
  const count = useSignal(0);
  return count;
};

このルールの間違ったコードの例

export const Counter = (() => {
  const count = useSignal(0);
});

use*メソッドは、component$関数内、またはuse*フック(例:useCounter)内でのみ使用できます。

valid-lexical-scope

tsc型チェッカーを使用して、ドル記号($)スコープでシリアル化できないデータのキャプチャを検出します。

referencesOutside

このルールの正しいコードの例

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>;
});

このルールの間違ったコードの例

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>;
});

式はシリアル化できないため、オプティマイザがコードを小さなチャンクに分割できるように、$( ... )でラップする必要があります。

invalidJsxDollar

このルールの正しいコードの例

import { component$, $ } from '@builder.io/qwik';
 
export const HelloWorld = component$(() => {
  const click = $(() => console.log());
  return (
    <button onClick$={click}>log it</button>
  );
});

このルールの間違ったコードの例

import { component$ } from '@builder.io/qwik';
 
export const HelloWorld = component$(() => {
  const click = () => console.log();
  return (
    <button onClick$={click}>log it</button>
  );
});

イベントハンドラーは${ ... }でラップする必要があります。

mutableIdentifier

このルールの正しいコードの例

import { component$ } from '@builder.io/qwik';
 
export const HelloWorld = component$(() => {
  const person = { name: 'Bob' };
 
  return (
    <button onClick$={() => {
      person.name = 'Alice';
    }}>
      {person.name}
    </button>
  );
});

このルールの間違ったコードの例

import { component$ } from '@builder.io/qwik';
 
export const HelloWorld = component$(() => {
  let personName = 'Bob';
 
  return (
    <button onClick$={() => {
      personName = 'Alice';
    }}>
      {personName}
    </button>
  );
});

単純な値は変更できません。代わりにオブジェクトを使用し、そのプロパティの1つを編集してください。

loader-location

loader$の宣言位置を検出します。

invalidLoaderLocation

このルールの正しいコードの例

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;
});

このルールの間違ったコードの例

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;
});

これはルートローダーの有効な場所ではありません。src/routesフォルダ内、layout.tsxまたはindex.tsxファイルでのみ使用できます。

missingExport

このルールの正しいコードの例

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;
});

このルールの間違ったコードの例

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;
});

ルートローダー関数はエクスポートする必要があります。

wrongName

このルールの正しいコードの例

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;
});

このルールの間違ったコードの例

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;
});

ルートローダー関数の名前はuseで始まる必要があります。

recommendedValue

このルールの正しいコードの例

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;
});

このルールの間違ったコードの例

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);

アロー関数をインラインで記述することをお勧めします。これにより、最適化ツールがクライアントビルドにサーバーコードが漏洩していないことを確認するのに役立ちます。

no-react-props

React固有のclassName/htmlForプロパティの使用を禁止します。

prefer

このルールの正しいコードの例

<MyReactComponent class="foo" for="#password" />;

このルールの間違ったコードの例

<MyReactComponent className="foo" htmlFor="#password" />;

classNameおよびhtmlForよりもclassおよびforプロパティを優先します。

prefer-classlist

classnamesヘルパーのインポートよりもclasslistプロパティの使用を強制します。classlistプロパティは、classnamesと同様に、オブジェクト{ [class: string]: boolean }を受け入れます。

preferClasslist

このルールの正しいコードの例

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>;
});

このルールの間違ったコードの例

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>;
});

オブジェクトに基づいてクラスを効率的に設定するには、サードパーティライブラリではなくclassプロパティを使用する必要があります。

jsx-no-script-url

javascript: URLを禁止します。

noJSURL

このルールの正しいコードの例

<button onClick$={() => alert('open the door please')>ring</button>

このルールの間違ったコードの例

<button onClick$="javascript:alert('open the door please')">ring</button>

jsx-key

イテレーター/コレクションリテラルでkeyプロパティが欠落していることを禁止します。

missingIterKey

このルールの正しいコードの例

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>
  );
});

このルールの間違ったコードの例

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>
  );
});

イテレーター内の要素にkeyプロパティがありません。

missingIterKeyUsePrag

このルールの正しいコードの例

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>
    )}
  );
});

このルールの間違ったコードの例

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]} />
      </>
    )}
  );
});

イテレーター内の要素にkeyプロパティがありません。keyプロパティはレンダリングパフォーマンスの向上に役立ちます。簡略化されたフラグメント構文はキーの提供をサポートしていません。代わりに<Fragment>を使用してください。

missingArrayKey

このルールの正しいコードの例

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>
  );
});

このルールの間違ったコードの例

import { component$ } from '@builder.io/qwik';
 
export const ColorList = component$(() => {
  const colors = ['red', 'green', 'blue'];
 
  return (
    <ul>
      {colors.map((color) => (
        <li>{color}</li>
      )}
    </ul>
  );
});

配列内の要素にkeyプロパティがありません。keyプロパティはレンダリングパフォーマンスの向上に役立ちます。

missingArrayKeyUsePrag

このルールの正しいコードの例

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>
    )}
  );
});

このルールの間違ったコードの例

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>
      </>
    )}
  );
});

配列内の要素にkeyプロパティがありません。keyプロパティはレンダリングパフォーマンスの向上に役立ちます。簡略化されたフラグメント構文はキーの提供をサポートしていません。代わりに<Fragment>を使用してください。

nonUniqueKeys

このルールの正しいコードの例

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>
  );
});

このルールの間違ったコードの例

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>
  );
});

keyプロパティは一意である必要があります。

unused-server

使用されていないserver$()関数を検出します。

unusedServer

このルールの正しいコードの例

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>
  );
);

このルールの間違ったコードの例

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>
  );
);

server$関数が宣言されていますが、使用されていません。

jsx-img

パフォーマンス上の理由から、常に<img>要素にwidthとheight属性を指定してください。レイアウトシフトの防止に役立ちます。

noLocalSrc

このルールの正しいコードの例

import Image from '~/media/image.png';
<Image />

このルールの間違ったコードの例

<img src="/image.png">

publicからの画像の提供は最適化されておらず、キャッシュもされません。代わりにESMを使用して画像をインポートしてください。

noWidthHeight

このルールの正しいコードの例

<img width="200" height="600" src="/static/images/portrait-01.webp">

このルールの間違ったコードの例

<img src="/static/images/portrait-01.webp">

パフォーマンス上の理由から、常に<img>要素にwidthとheight属性を指定してください。レイアウトシフトの防止に役立ちます。

jsx-a

完璧なSEOスコアを得るには、常に<a>要素にhref属性を指定してください。

noHref

no-use-visible-task

useVisibleTask$()関数を検出します。

noUseVisibleTask

貢献者

このドキュメントの改善に貢献してくださった皆様に感謝いたします!

  • zanettin
  • hbendev
  • manucorporat
  • gioboa
  • maiieul