開発者向けSOLIIDS入門


SolidJSは非常に高速かつ小さなWebアプリケーションを構築するためのUIライブラリとして牽引されている.一見して、固体は反応とはあまり異なりません.ソリッドはまた、JSXを使用して、それは反応フックに似たAPIを持っており、一方向のデータフロー、不変のインターフェイスなどと反応するのと同じ哲学に従います.
import { render } from "solid-js/web";
import { onCleanup, createSignal } from "solid-js";

function App() {
  const [count, setCount] = createSignal(0);
  const interval = setInterval(() => setCount((count) => count + 1), 1000);
  onCleanup(() => clearInterval(interval));

  return <div>Counter: {count()}</div>;
}

render(() => <App />, document.getElementById("app"));
しかし、固体が基本的に異なっているので、見てみましょう.まず最初に、UIを更新するのに仮想DOM Diffingを使用しません.代わりに、ソリッドは、アプリケーションの状態を保持し、自動的に依存関係を追跡する反応プリミティブに依存しているので、データの変更の部分は、それがすぐに正確に何を更新する必要が知っている.この細粒度の反応性システムは、固体に一貫して最高の速度と記憶を許しますbenchmarks UIライブラリ用.
第二に、ソリッドは、それが無効なグラフをセットアップして、束サイズを減らすためにtreeshakingを扱うためにコンパイラを使用する予めコンパイルされたアプローチをします.このコンパイラのおかげで、固体アプリケーションはcomparison その他のUIライブラリに.
この記事はSolidJsの基礎を学ぶために開発者の反応を支援することを目的としています.次のトピックを取り上げます
  • コンポーネントの定義
  • コンポーネント
  • コンポーネントライフサイクル
  • コンポーネント通信
  • イベント処理
  • refsで働く
  • エラー処理
  • コード再利用
  • コンポーネントの定義


    ソリッドアプリケーションでは、コンポーネントはJSX要素を返す関数です.クラスのコンポーネントがサポートされていません.JSXコードはDOMを直接更新する関数にコンパイルされることに注意しましょう.すべてのUPDATEでDOMノードを再利用するのを避けるために、Solidif/else , switch ステートメントとArray.prototype.map . 最も重要なコンポーネントはShow , Switch and For :
    <Show
      when={loggedIn()}
      fallback={<button onClick={toggle}>Log in</button>}
    >
      <button onClick={toggle}>Log out</button>
    </Show>
    
    <Switch fallback={<p>Normal temperature</p>}>
      <Match when={temp() >= 40}>
        <p>Too hot</p>
      </Match>
      <Match when={temp() <= 10}>
        <p>Too cold</p>
      </Match>
    </Switch>
    
    <For each={articles()}>{(a, index) =>
      <li>{index() + 1}: {a.title}</li>
    }</For>
    
    同様に、すべてのアップデートで子ノードを再利用しないようにするためには、基本的に子プロセスヘルパーを使用し、基本的に子プロセスのプロップを作成します.
    function MyComponent(props) {
      const c = children(() => props.children);
      return (
        <div>
          {c()}
        </div>
      );
    }
    

    コンポーネント


    固体の反応性の礎石は反応と反応に似ているuseState and useEffect フック
    import { createSignal, createEffect } from "solid-js";
    
    function App() {
      const [count, setCount] = createSignal(0);
      createEffect(() => {
        console.log("Count: ", count());
      });
    
      return <button onClick={() => setCount((c) => c + 1)}>{count}</button>;
    }
    
    しかし、信号は非常にuseState フックを次のように説明します.
  • あなただけの呼び出し中useState() 機能コンポーネントまたはカスタムフックの中から、コールすることができますcreateSignal() どこからでも.コンポーネント内で呼び出されると、シグナルはそのコンポーネントのローカル状態を表します.さもなければ、シグナルはどんなコンポーネントも彼らのUIをレンダリングするために輸入して、使うことができる外部の状態を表します.
  • さらに重要なことに、シグナルは自動的にデータに依存する関数を追跡し、データが変化するたびにこれらの関数を呼び出します.返されるタプルの最初の要素はcreateSignal() データ自体ではなく、getter関数です.getter関数が呼び出されると、呼び出し元の関数(グローバルスタックから取得された)がシグナルのサブスクリプションリストに追加されます.
  • 反応に似ているuseEffect フック.createEffect() シグナルが変更に依存するたびに実行する副作用を定義します.しかし、固体の自動依存性追跡のおかげで、依存関係リストを明示的に提供する必要はありません.

    コンポーネントライフサイクル


    反応すると、コンポーネントの状態が変化するたびに、コンポーネント関数が再起動します.対照的に、固体コンポーネント関数は決して再実行されません.コンポーネントは、必要なシグナルとエフェクトを作成するために一度だけ実行されます.その後、コンポーネントが消えます.それは、我々が我々が反応または他のライブラリでするように、コンポーネントライフサイクルイベントへのアクセスを持っていないことを意味します.
    しかし、ソリッドはonMount and onCleanup . onMount すべての初期のレンダリングが行われた後、一度だけ実行される特殊効果と見なされることができます.最も一般的なユースケースは、画面がロードされたときにデータを取得することです.
    import { createSignal, onMount } from "solid-js";
    
    function App() {
      const [data, setData] = createSignal();
    
      onMount(async () => {
        const res = await fetch(`/path/to/your/api`);
        setData(await res.json());
      });
    
      return (/* JSX to render UI based on data */);
    }
    
    onCleanup コンポーネント(第1の例を参照)、効果(以下の例)、または反応システムの同期実行の一部である任意のスコープで呼び出すことができます.onCleanup は、スコープが破棄されたり再評価された場合に実行されます.
    import { createSignal, createEffect, onCleanup } from "solid-js";
    
    function App() {
      const [counting, setCounting] = createSignal(false);
      const [count, setCount] = createSignal(0);
    
      createEffect(() => {
        if (counting()) {
          const c = setInterval(() => setCount((val) => val + 1), 300);
          onCleanup(() => clearInterval(c));
        }
      });
    
      return (
        <div>
          <button type="button" onClick={() => setCounting((val) => !val)}>
            {counting() ? "Stop" : "Start"}
          </button>
          <p>Counter: {count()}</p>
        </div>
      );
    }
    

    コンポーネント通信


    この点では、固体は非常に反応と同じです.親コンポーネントから子プロセスへのデータを渡すためのプロップを使用します.コンテキストAPIを使用してデータを子孫コンポーネントに渡します.
    しかし、警告があります.通常、小道具の構造を変更するべきではありません.そうすることで、子プロセスのUIがprop値が変更されると更新されないことを意味します.補償として、ソリッドは支柱で働くために2つのヘルパーを提供します:mergeProps() and splitProps() .
    // DON'T do this
    function Greeting({ name, greeting = "Hi" }) {
      return <h3>{greeting}, {name}!</h3>
    }
    
    // use mergeProps() to set default values
    function Greeting(props) {
      const merged = mergeProps({ greeting: "Hi" }, props);
      return <h3>{merged.greeting}, {merged.name}!</h3>
    }
    
    // DON'T do this
    export default function Greeting(props) {
      const { greeting, name, ...others } = props;
      return <h3 {...others}>{greeting}, {name}!</h3>
    }
    
    // use splitProps() instead of the rest syntax
    function Greeting(props) {
      const [local, others] = splitProps(props, ["greeting", "name"]);
      return <h3 {...others}>{local.greeting}, {local.name}!</h3>
    }
    

    イベント処理


    反応のように、固体は一方向データフローを支持するだけです.入力バインディングの組み込みメカニズムはありません.しかし、反応とは異なり、固体アプリケーションは、合成イベントよりむしろDOMイベントを直接使用します.
    function App() {
      const [name, setName] = createSignal("World");
    
      return (
        <div>
          <input
            type="text"
            value={name()}
            onInput={(evt) => setName(evt.currentTarget.value)}
          />
          <p>Hello, {name()}!</p>
        </div>
      );
    }
    

    refsで働く


    固体のアプリケーションでrefsを使用することは、反応とそれとは大きく異なりません.基本的には、ローカル変数を宣言し、名前を付けたプロップに割り当てることもできますref , またはコールバックを使用する
    // local variable
    function SimpleForm() {
      let ref;
      onMount(() => ref.focus());
      return (<input ref={ref} />);
    }
    
    // ref callback
    function SimpleForm() {
      return (
        <input ref={el => {
          onMount(() => el.focus())
        }} />
      );
    }
    

    エラー処理


    反応から固体が借りるというもう一つの考えは、エラー境界要素です.しかし、手動で実装する必要はありませんErrorBoundary 組み込みコンポーネントです.
    import { ErrorBoundary } from "solid-js";
    
    <ErrorBoundary fallback={err => {
      // report error
      console.log(err);
    
      // fallback UI
      return (/* JSX */)
    }}>
      {/* your component tree */}
    </ErrorBoundary>
    

    コード再利用


    反応では、最も人気の高いコンポーネントで、コードを再利用するための複数のテクニックを持って、小道具、およびカスタムフックをレンダリングします.同様のテクニックを固体でも使えます.以下の例は、異なるUISで簡単に使用できる再利用可能なセルフランニングクロックの3つの実装です.
    高次成分(アドホック)
    支柱を描く
    コードの再利用のようなフックの反応
    これらのテクニックに加えて、ソリッドは、カスタムディレクティブとして再利用可能な動作を定義することができます.ディレクティブは、それが装飾する要素がDOMに追加されたときに呼び出される関数です.この関数は、DOM要素と、ディレクティブのパラメータを取得するGetter関数との2つの引数をとります.以下はユーザーが要素の境界の外側をクリックしたかどうかを示すディレクティブディレクティブです.

    結論


    Solidjsは信じられないほどのパフォーマンスと非常に小さなバンドルサイズを提供しながら、我々はすべての愛シンプルなプログラミングモデルを保持することができます.比較的新しい図書館として、固体の生態系とコミュニティはまだ小さいです、しかし、より多くの人々がその可能性を知るようになると、それは変わるかもしれません.この文書のように、固体のGithubレポは16千の星を持っています、そして、プロジェクトはCloudflare、Netlify、Vercelのような評判の良い会社によって後援されます.
    この記事はsolidjsの使用に関する基本的な話題のみをカバーしています.私はそれを試して固体を与えたい場合は、いくつかの時間を節約することができます願っています.今後の記事は、状態管理、サスペンスAPI、およびサーバーのレンダリングなどの詳細なトピックに対応します.じゃあまた
    注:この記事は、最初のHackerSaintdifferent title . ここでは、オリジナルのタイトルとカスタムディレクティブの追加部分を再発行します.