Qwik入門

コンポーネント

QwikコンポーネントはReactコンポーネントと非常によく似ています。JSXを返す関数です。ただし、component$(...)を使用する必要があり、イベントハンドラには$サフィックスを付ける必要があり、状態はuseSignal()を使用して作成され、classclassNameの代わりに使用され、その他にもいくつかの違いがあります。

src/components/my-other-component/index.tsx
import { component$, Slot } from '@builder.io/qwik';
import type { ClassList } from '@builder.io/qwik'
 
export const MyOtherComponent = component$((props: { class?: ClassList }) => { // ✅
  return <div class={class}><Slot /></div>;
});
import { component$, useSignal } from '@builder.io/qwik';
 
// Other components can be imported and used in JSX.
import { MyOtherComponent } from './my-other-component';
 
interface MyComponentProps {
  step: number;
}
 
// Components are always declared with the `component$` function.
export const MyComponent = component$((props: MyComponentProps) => {
  // Components use the `useSignal` hook to create reactive state.
  const count = useSignal(0); // { value: 0 }
  return (
    <>
      <button
        onClick$={() => {
          // Event handlers have the `$` suffix.
          count.value = count.value + props.step;
        }}
      >
        Increment by {props.step}
      </button>
      <main
        class={{
          even: count.value % 2 === 0,
          odd: count.value % 2 === 1,
        }}
      >
        <h1>Count: {count.value}</h1>
        <MyOtherComponent class="correct-way"> {/* ✅ */}
          {count.value > 10 && <p>Count is greater than 10</p>}
          {count.value > 10 ? <p>Count is greater than 10</p> : <p>Count is less than 10</p>}
        </MyOtherComponent>
      </main>
    </>
  );
});

アイテムのリストのレンダリング

Reactと同様に、map関数を使用してアイテムのリストをレンダリングできますが、リスト内の各アイテムには一意のkeyプロパティが必要です。keyは文字列または数値でなければならず、リスト内では一意である必要があります。

import { component$, useSignal } from '@builder.io/qwik';
import { US_PRESIDENTS } from './presidents';
 
export const PresidentsList = component$(() => {
  return (
    <ul>
      {US_PRESIDENTS.map((president) => (
        <li key={president.number}>
          <h2>{president.name}</h2>
          <p>{president.description}</p>
        </li>
      ))}
    </ul>
  );
});

イベントハンドラの再利用

イベントハンドラは、JSXノード間で再利用できます。これは、$(...handler...)を使用してハンドラを作成することで行われます。

import { $, component$, useSignal } from '@builder.io/qwik';
 
interface MyComponentProps {
  step: number;
}
 
// Components are always declared with the `component$` function.
export const MyComponent = component$(() => {
  const count = useSignal(0);
 
  // Notice the `$(...)` around the event handler function.
  const inputHandler = $((event, elem) => {
    console.log(event.type, elem.value);
  });
 
  return (
    <>
      <input name="name" onInput$={inputHandler} />
      <input
        name="password"
        onInput$={inputHandler}
      />
    </>
  );
});

コンテンツプロジェクション

コンテンツプロジェクションは、@builder.io/qwikからエクスポートされる<Slot/>コンポーネントによって行われます。スロットには名前を付けることができ、q:slot属性を使用して投影できます。

// File: src/components/Button/Button.tsx
import { component$, Slot } from '@builder.io/qwik';
import styles from './Button.module.css';
 
export const Button = component$(() => {
  return (
    <button class={styles.button}>
      <div class={styles.start}>
        <Slot name="start" />
      </div>
      <Slot />
      <div class={styles.end}>
        <Slot name="end" />
      </div>
    </button>
  );
});
 
export default component$(() => {
  return (
    <Button>
      <span q:slot="start">📩</span>
      Hello world
      <span q:slot="end">🟩</span>
    </Button>
  );
});

useフックのルール

useで始まるメソッドは、useSignal()useStore()useOn()useTask$()useLocation()など、Qwikでは特別なものです。Reactフックと非常によく似ています。

  • コンポーネント$内でのみ呼び出すことができます。
  • 条件式やループ内ではなく、コンポーネント$の最上位レベルからのみ呼び出すことができます。

スタイル

Qwikは、CSSモジュール、Tailwind、グローバルCSSインポート、useStylesScoped$()を使用した遅延読み込みスコープ付きCSSをすぐにサポートしています。CSSモジュールは、Qwikコンポーネントをスタイル設定するための推奨方法です。

CSSモジュール

CSSモジュールを使用するには、.module.cssファイルを作成します。たとえば、src/components/MyComponent/MyComponent.module.cssです。

src/components/MyComponent/MyComponent.module.css
.container {
  background-color: red;
}

次に、コンポーネントにCSSモジュールをインポートします。

src/components/MyComponent/MyComponent.tsx
import { component$ } from '@builder.io/qwik';
import styles from './MyComponent.module.css';
 
export default component$(() => {
  return <div class={styles.container}>Hello world</div>;
});

Qwikは、CSSクラスにclassNameではなくclassを使用することに注意してください。

$(...)ルール

$(...)関数と$で終わる関数は、$()useTask$()useVisibleTask$()など、Qwikでは特殊です。末尾の$は遅延読み込み境界を表します。任意の$関数の最初の引数には、いくつかのルールが適用されます。これはjQueryとは全く関係ありません。

  • 最初の引数はインポートされた変数でなければなりません。
  • 最初の引数は、同じモジュールの最上位レベルで宣言された変数でなければなりません。
  • 最初の引数は、任意の変数の式でなければなりません。
  • 最初の引数が関数の場合、同じモジュールの最上位レベルで宣言されている変数、または値がシリアライズ可能な変数のみをキャプチャできます。シリアライズ可能な値には、stringnumberbooleannullundefinedArrayObjectDateRegExpMapSetBigIntPromiseErrorJSXノードSignalStore、さらにはHTMLElementsが含まれます。
// Valid examples of `$` functions.
import { $, component$, useSignal } from '@builder.io/qwik';
import { importedFunction } from './my-other-module';
 
export function exportedFunction() {
  console.log('exported function');
}
 
export default component$(() => {
  // The first argument is a function.
  const valid1 = $((event, elem) => {
    console.log(event.type, elem.value);
  });
 
  // The first argument is an imported identifier.
  const valid2 = $(importedFunction);
 
  // The first argument is an identifier declared at the top level of the same module.
  const valid3 = $(exportedFunction);
 
  // The first argument is an expression without local variables.
  const valid4 = $([1, 2, { a: 'hello' }]);
 
  // The first argument is a function that captures a local variable.
  const localVariable = 1;
  const valid5 = $((event) => {
    console.log('local variable', localVariable);
  });
});

無効な$関数の例をいくつか示します。

// Invalid examples of `$` functions.
import { $, component$, useSignal } from '@builder.io/qwik';
import { importedVariable } from './my-other-module';
 
export default component$(() => {
  const unserializable = new CustomClass();
  const localVariable = 1;
 
  // The first argument is a local variable.
  const invalid1 = $(localVariable);
 
  // The first argument is a function that captures an unserializable local variable.
  const invalid2 = $((event) => {
    console.log('custom class', unserializable);
  });
 
  // The first argument is an expression that uses a local variable.
  const invalid3 = $(localVariable + 1);
 
  // The first argument is an expression that uses an imported variable.
  const invalid4 = $(importedVariable + 'hello');
});

リアクティブ状態

useSignal(initialValue?)

useSignal()は、リアクティブな状態を作成する主な方法です。シグナルはコンポーネント間で共有でき、シグナルを読み取るコンポーネントまたはタスク(signal.valueを実行する)は、シグナルが変更されるとレンダリングされます。

// Typescript definition for `Signal<T>` and `useSignal<T>`
 
export interface Signal<T> {
  value: T;
}
 
export const useSignal: <T>(value?: T | (() => T)): Signal<T>;

useSignal(initialValue?)は、オプションの初期値を受け取り、Signal<T>オブジェクトを返します。Signal<T>オブジェクトには、読み書きできるvalueプロパティがあります。コンポーネントまたはタスクがvalueプロパティにアクセスすると、自動的にサブスクリプションが作成されるため、valueが変更されると、valueを読み取るすべてのコンポーネント、タスク、または他の計算されたシグナルが再評価されます。

useStore(initialValue?)

useStore(initialValue?)useSignalに似ていますが、リアクティブなJavaScriptオブジェクトを作成するという点が異なります。これにより、オブジェクトのプロパティごとに、シグナルのvalueと同様に、リアクティブ性が実現されます。内部的には、useStoreはすべてのプロパティアクセスをインターセプトするProxyオブジェクトを使用して実装されており、プロパティをリアクティブにします。

// Typescript definition `useStore<T>`
 
// The `Reactive<T>` is a reactive version of the `T` type, every property of `T` behaves like a `Signal<T>`.
export interface Reactive<T extends Record<string, any>> extends T {}
 
export interface StoreOptions {
  // If `deep` is true, then nested property of the store will be wrapped in a `Signal<T>`.
  deep?: boolean;
}
export const useStore: <T>(value?: T | (() => T), options?: StoreOptions): Reactive<T>;

実際には、useSignaluseStoreは非常に似ており(useSignal(0) === useStore({ value: 0 }))、ほとんどの場合、useSignalの方が好ましいです。useStoreの使用例をいくつか挙げます。

  • 配列でリアクティビティが必要な場合。
  • プロパティを簡単に追加できるリアクティブなオブジェクトが必要な場合。
import { component$, useStore } from '@builder.io/qwik';
 
export const Counter = component$(() => {
  // The `useStore` hook is used to create a reactive store.
  const todoList = useStore(
    {
      array: [],
    },
    { deep: true }
  );
 
  // todoList.array is a reactive array, so we can push to it and the component will re-render.
 
  return (
    <>
      <h1>Todo List</h1>
      <ul>
        {todoList.array.map((todo) => (
          <li key={todo.id}>
            <input
              type="checkbox"
              checked={todo.completed}
              onInput$={() => {
                // todoList is a reactive store
                // because we used `deep: true`, the `todo` object is also reactive.
                // so we can change the `completed` property and the component will re-render.
                todo.completed = !todo.completed;
              }}
            />
            {todo.text}
          </li>
        ))}
      </ul>
    </>
  );
});

useTask$(() => { ... })

useTask$は非同期タスクを作成するために使用されます。タスクは副作用の実装、重い計算の実行、レンダリングライフサイクルの一部としての非同期コードの実行に役立ちます。useTask$タスクは最初のレンダリングの前に実行され、その後、追跡されたシグナルまたはストアが変更されるたびに、タスクは再実行されます。

import { component$, useSignal, useTask$ } from '@builder.io/qwik';
 
export const Counter = component$(() => {
  const page = useSignal(0);
  const listOfUsers = useSignal([]);
 
  // The `useTask$` hook is used to create a task.
  useTask$(() => {
    // The task is executed before the first render.
    console.log('Task executed before first render');
  });
 
  // You can create multiple tasks, and they can be async.
  useTask$(async (taskContext) => {
    // Since we want to re-run the task whenever the `page` changes,
    // we need to track it.
    taskContext.track(() => page.value);
    console.log('Task executed before the first render AND when page changes');
    console.log('Current page:', page.value);
 
    // Tasks can run async code, such as fetching data.
    const res = await fetch(`https://api.randomuser.me/?page=${page.value}`);
    const json = await res.json();
 
    // Assigning to a signal will trigger a re-render.
    listOfUsers.value = json.results;
  });
 
  return (
    <>
      <h1>Page {page.value}</h1>
      <ul>
        {listOfUsers.value.map((user) => (
          <li key={user.login.uuid}>
            {user.name.first} {user.name.last}
          </li>
        ))}
      </ul>
      <button onClick$={() => page.value++}>Next Page</button>
    </>
  );
});

useTask$()はSSR中はサーバーで、コンポーネントがクライアントに最初にマウントされた場合はブラウザで実行されます。そのため、サーバーでは使用できないため、タスク内でDOM APIにアクセスするのは良い考えではありません。代わりに、イベントハンドラまたはuseVisibleTask$()を使用して、クライアント/ブラウザでのみタスクを実行する必要があります。

useVisibleTask$(() => { ... })

useVisibleTask$は、コンポーネントがDOMに最初にマウントされた直後に発生するタスクを作成するために使用されます。useTask$に似ていますが、クライアントでのみ実行され、最初のレンダリング後に実行されます。レンダリング後に実行されるため、DOMの検査やブラウザAPIの使用が可能です。

import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik';
 
export const Clock = component$(() => {
  const time = useSignal(0);
 
  // The `useVisibleTask$` hook is used to create a task that runs eagerly on the client.
  useVisibleTask$((taskContext) => {
    // Since this VisibleTask is not tracking any signals, it will only run once.
 
    const interval = setInterval(() => {
      time.value = new Date();
    }, 1000);
 
    // The `cleanup` function is called when the component is unmounted, or when the task is re-run.
    taskContext.cleanup(() => clearInterval(interval));
  });
 
  return (
    <>
      <h1>Clock</h1>
      <h1>Seconds passed: {time.value}</h1>
    </>
  );
});

Qwikはユーザー操作前にブラウザでJavaScriptを実行しないため、useVisibleTask$()はクライアントで熱心に実行される唯一のAPIであり、そのため、次のような操作を行うのに適した場所です。

  • DOM APIへのアクセス
  • ブラウザ専用のライブラリの初期化
  • 分析コードの実行
  • アニメーションまたはタイマーの開始。

useVisibleTask$()はサーバーでは実行されないため、データの取得には使用しないでください。代わりに、useTask$()を使用してデータを取得し、useVisibleTask$()を使用してアニメーションの開始などの操作を行う必要があります。useVisibleTask$()の乱用はパフォーマンスの低下につながる可能性があります。

ルーティング

Qwikにはファイルベースのルーターが付属しており、Next.jsに似ていますが、いくつかの違いがあります。ルーターはファイルシステム、特にsrc/routes/に基づいています。src/routes/の下のフォルダに新しいindex.tsxファイルを作成すると、新しいルートが作成されます。たとえば、src/routes/home/index.tsx/home/にルートを作成します。

src/routes/home/index.tsx
 
import { component$ } from '@builder.io/qwik';
 
export default component$(() => {
  return <h1>Home</h1>;
});

コンポーネントをデフォルトエクスポートとしてエクスポートすることが非常に重要です。そうでないと、ルーターはコンポーネントを見つけることができません。

ルートパラメータ

ルートパスに[param]を含むフォルダを追加することで、動的ルートを作成できます。たとえば、src/routes/user/[id]/index.tsx/user/:id/にルートを作成します。ルートパラメータにアクセスするには、@builder.io/qwik-cityからエクスポートされたuseLocationフックを使用できます。

src/routes/user/[userID]/index.tsx
 
import { component$ } from '@builder.io/qwik';
import { useLocation } from '@builder.io/qwik-city';
 
export default component$(() => {
  const loc = useLocation();
  return (
    <main>
      {loc.isNavigating && <p>Loading...</p>}
      <h1>User: {loc.params.userID}</h1>
      <p>Current URL: {loc.url.href}</p>
    </main>
  );
});

useLocation()はリアクティブなRouteLocationオブジェクトを返し、ルートが変更されるたびに再レンダリングされます。RouteLocationオブジェクトには、次のプロパティがあります。

/**
 * The current route location returned by `useLocation()`.
 */
export interface RouteLocation {
  readonly params: Readonly<Record<string, string>>;
  readonly url: URL;
  readonly isNavigating: boolean;
}

他のルートへのリンク

他のルートへのリンクを作成するには、@builder.io/qwik-cityからエクスポートされたLinkコンポーネントを使用できます。Linkコンポーネントは、<a> HTMLAnchorElementのプロパティをすべて受け取ります。唯一の違いは、完全なページナビゲーションを行う代わりに、Qwikルーターを使用してSPAナビゲーションでルートに移動することです。

src/routes/index.tsx
 
import { component$ } from '@builder.io/qwik';
import { Link } from '@builder.io/qwik-city';
 
export default component$(() => {
  return (
    <>
      <h1>Home</h1>
      <Link href="/about/">SPA navigate to /about/</Link>
      <a href="/about/">Full page navigate to /about/</a>
    </>
  );
});

データの取得/読み込み

サーバーからデータを読み込む推奨方法は、@builder.io/qwik-cityからエクスポートされたrouteLoader$()関数を使用することです。routeLoader$()関数は、ルートがレンダリングされる前にサーバーで実行されるデータローダーを作成するために使用されます。routeLoader$()の戻り値は、ルートファイルから名前付きエクスポートとしてエクスポートする必要があります。つまり、src/routes/内のindex.tsxでのみ使用できます。

src/routes/user/[userID]/index.tsx
 
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
 
// The `routeLoader$()` function is used to create a data loader that will be executed on the server before the route is rendered.
// The return of `routeLoader$()` is a custom use hook, which can be used to access the data returned from `routeLoader$()`.
export const useUserData = routeLoader$(async (requestContext) => {
  const user = await db.table('users').get(requestContext.params.userID);
  return {
    name: user.name,
    email: user.email,
  };
});
 
export default component$(() => {
  // The `useUserData` hook will return a `Signal` containing the data returned from `routeLoader$()`, which will re-render the component, whenever the navigation changes, and the routeLoader$() is re-run.
  const userData = useUserData();
  return (
    <main>
      <h1>User data</h1>
      <p>User name: {userData.value.name}</p>
      <p>User email: {userData.value.email}</p>
    </main>
  );
});
 
// Exported `head` function is used to set the document head for the route.
export const head: DocumentHead = ({resolveValue}) => {
  // It can use the `resolveValue()` method to resolve the value from `routeLoader$()`.
  const user = resolveValue(useUserData);
  return {
    title: `User: "${user.name}"`,
    meta: [
      {
        name: 'description',
        content: 'User page',
      },
    ],
  };
};

routeLoader$()関数は、Promiseを返す関数を取得します。Promiseはサーバーで解決され、解決された値はuseCustomLoader$()フックに渡されます。useCustomLoader$()フックは、routeLoader$()関数によって作成されるカスタムフックです。useCustomLoader$()フックは、routeLoader$()関数から返されたPromiseの解決済み値を含むSignalを返します。useCustomLoader$()フックは、ルートが変更され、routeLoader$()関数が再実行されるたびにコンポーネントを再レンダリングします。

フォーム送信の処理

Qwikは、サーバーでフォームリクエストを処理するために、@builder.io/qwik-cityからエクスポートされたrouteAction$() APIを提供します。routeAction$()は、フォームが送信されたときにサーバーでのみ実行されます。

src/routes/user/[userID]/index.tsx
 
import { component$ } from '@builder.io/qwik';
import { routeAction$, Form, zod$, z } from '@builder.io/qwik-city';
 
// The `routeAction$()` function is used to create a data loader that will be executed on the server when the form is submitted.
// The return of `routeAction$()` is a custom use hook, which can be used to access the data returned from `routeAction$()`.
export const useUserUpdate = routeAction$(async (data, requestContext) => {
  const user = await db.table('users').get(requestContext.params.userID);
  user.name = data.name;
  user.email = data.email;
  await db.table('users').put(user);
  return {
    user,
  };
}, zod$({
  name: z.string(),
  email: z.string(),
}));
 
export default component$(() => {
  // The `useUserUpdate` hook will return an `ActionStore<T>` containing the `value` returned from `routeAction$()`, and some other properties, such as `submit()`, which is used to submit the form programmatically, and `isRunning`. All of these properties are reactive, and will re-render the component whenever they change.
  const userData = useUserUpdate();
  // userData.value is the value returned from `routeAction$()`, which is `undefined` before the form is submitted.
  // userData.formData is the form data that was submitted, it is `undefined` before the form is submitted.
  // userData.isRunning is a boolean that is true when the form is being submitted.
  // userData.submit() is a function that can be used to submit the form programmatically.
  // userData.actionPath is the path to the action, which is used to submit the form.
  return (
    <main>
      <h1>User data</h1>
      <Form action={userData}>
        <div>
          <label>User name: <input name="name" defaultValue={userData.formData?.get('name')} /></label>
        </div>
        <div>
          <label>User email: <input name="email" defaultValue={userData.formData?.get('email')} /></label>
        </div>
        <button type="submit">Update</button>
      </Form>
    </main>
  );
});

routeAction$()は、@builder.io/qwik-cityからエクスポートされたFormコンポーネントと組み合わせて使用されます。Formコンポーネントは、ネイティブHTML<form>要素をラップしたものです。Formコンポーネントは、actionプロパティとしてActionStore<T>を取得します。ActionStore<T>は、routeAction$()関数の戻り値です。

ブラウザでのみコードを実行する

Qwikはサーバーとブラウザで同じコードを実行するため、サーバーでコードが実行されると存在しないため、コードでwindowやその他のブラウザAPIを使用することはできません。

windowdocumentlocalStoragesessionStoragewebglなどのブラウザAPIにアクセスする場合は、ブラウザAPIにアクセスする前にコードがブラウザで実行されているかどうかを確認する必要があります。

import { component$, useTask$, useVisibleTask$, useSignal } from '@builder.io/qwik';
import { isBrowser } from '@builder.io/qwik/build';
 
export default component$(() => {
  const ref = useSignal<Element>();
 
  // useVisibleTask$ will only run in the browser
  useVisibleTask$(() => {
    // No need to check for `isBrowser` before accessing the DOM, because useVisibleTask$ will only run in the browser
    ref.value?.focus();
    document.title = 'Hello world';
  });
 
  // useTask might run on the server, so you need to check for `isBrowser` before accessing the DOM
  useTask$(() => {
    if (isBrowser) {
      // This code will only run in the browser only when the component is first rendered there
      ref.value?.focus();
      document.title = 'Hello world';
    }
  });
 
  return (
    <button
      ref={ref}
      onClick$={() => {
        // All event handlers are only executed in the browser, so it's safe to access the DOM
        ref.value?.focus();
        document.title = 'Hello world';
      }}
    >
      Click me
    </button>
  );
});

useVisibleTask$(() => { ... })

このAPIは、クライアント/ブラウザでのみ実行されることが保証されているVisibleTaskを宣言します。サーバーでは決して実行されません。

JSXイベントハンドラ

onClick$onInput$などのJSXハンドラは、クライアントでのみ実行されます。これらはDOMイベントであるためです。サーバーにDOMがないため、サーバーでは実行されません。

サーバーでのみコードを実行する

データの取得やデータベースへのアクセスなど、サーバーでのみコードを実行する必要がある場合があります。この問題を解決するために、Qwikはサーバーでのみコードを実行するためのいくつかのAPIを提供します。

import { component$, useTask$ } from '@builder.io/qwik';
import { server$, routeLoader$ } from '@builder.io/qwik/qwik-city';
import { isServer } from '@builder.io/qwik/build';
 
 
export const useGetProducts = routeLoader$((requestEvent) => {
  // This code will only run on the server
  const db = await openDB(requestEvent.env.get('DB_PRIVATE_KEY'));
  const product = await db.table('products').select();
  return product;
})
 
const encryptOnServer = server$(function(message: string) {
  // `this` is the `requestEvent
  const secretKey = this.env.get('SECRET_KEY');
  const encryptedMessage = encrypt(message, secretKey);
  return encryptedMessage;
});
 
export default component$(() => {
  useTask$(() => {
    if () {
      // This code will only run on the server only when the component is first rendered in the server
    }
  });
 
  return (
    <>
      <button
        onClick$={server$(() => {
          // This code will only run on the server when the button is clicked
        })}
      >
        Click me
      </button>
 
      <button
        onClick$={() => {
          // This code will call the server function, and wait for the result
          const encrypted = await encryptOnServer('Hello world');
          console.log(encrypted);
        }}
      >
        Click me
      </button>
    </>
  );
});

routeAction$()

routeAction$()は、サーバーでのみ実行される特別なコンポーネントです。フォームの送信やその他の操作を処理するために使用されます。たとえば、これを用いてユーザーをデータベースに追加し、ユーザーのプロファイルページにリダイレクトできます。

routeLoader$()

routeLoader$()は、サーバーでのみ実行される特別なコンポーネントです。データを取得し、ページをレンダリングするために使用されます。たとえば、APIからデータを取得し、そのデータを使用してページをレンダリングするために使用できます。

server$((...args) => { ... })

server$()は、サーバーでのみ実行される関数を宣言する特別な方法です。クライアントから呼び出された場合、RPC呼び出しのように動作し、サーバーで実行されます。シリアライズ可能な引数を任意に受け取り、シリアライズ可能な値を任意に返すことができます。

isServer & isBrowser 条件文

if(typeof window !== 'undefined')の代わりに、@builder.io/qwik/buildからエクスポートされるisServerisBrowserのブール型のヘルパーを使用することをお勧めします。これにより、コードがブラウザでのみ実行されることが保証されます。ブラウザ環境をより適切に検出するための、より堅牢なチェックが含まれています。

参照のためのソースコードです。

export const isBrowser: boolean = /*#__PURE__*/ (() =>
  typeof window !== 'undefined' &&
  typeof HTMLElement !== 'undefined' &&
  !!window.document &&
  String(HTMLElement).includes('[native code]'))();
 
export const isServer: boolean = !isBrowser;

参照のために、これらをインポートする方法です。

import {isServer, isBrowser} from '@builder.io/qwik/build';
 
// inside component$
 
useTask$(({ track }) => {
  track(() => interactionSig.value) <-- tracks on the client when a signal has changed.
 
  // server code
 
  if (isServer) return;
 
  // client code here
});
 
//

貢献者

このドキュメントを改善するお手伝いをしてくださったすべての貢献者に感謝します!

  • manucorporat
  • AnthonyPAlicea
  • the-r3aper7
  • igorbabko
  • mrhoodz
  • hbendev
  • willnguyen1312
  • julianobrasil
  • devagja
  • vanvuongngo
  • iancharlesdouglas
  • adamdbradley
  • hamatoyogi
  • aendel
  • maiieul
  • patrickjs