Stencil(v3)で作成したコンポーネントに、Storeを追加する

Stencilは、アプリやリッチな機能を持つWebコンポーネントを作成する際に、@stencil/storeを使用してストア機能を追加することができます。この記事では、@stencil/storeを使用したストアの作成方法や使用例が紹介されています。ストアを作成するためには、createStore関数を使用し、グローバル変数のようにストアを扱うことができます。また、onChange関数を使用して非同期処理を実装する方法や、setやget関数を使用してイベントを設定する方法も紹介されています。ストアを使用することで、コンポーネントの表示と処理を切り分けることができます。

広告ここから
広告ここまで

目次

    Stencilでアプリを作る場合、もしくはすこしリッチな機能を持つWeb Componentをつくりたい場合に、StencilではStore機能を追加できます。

    この記事では、@stencil/storeを使った時の覚書を紹介します。

    ライブラリのInstall

    StencilにStore機能を追加するには、専用のライブラリを追加します。

    npm install @stencil/store --save-dev

    ストアをコンポーネントに組み込む

    インストールに成功したら、早速組み込みましょう。

    createStoreでストアを作成する

    まずはStoreを作成します。createStoreの引数には、初期値(initialState)を入れましょう。

    import { createStore } from '@stencil/store';
    
    export const store = createStore({
      count: 0,
      message: ''
    })

    同じStoreを参照できるようにするため、createStoreの結果をexportして、コンポーネント側はそれをimportするやり方がよさそうです。

    ボタンクリックで、ステートを変更する

    あとはimportしたstoreを、グローバル変数のように扱うだけです。

    
      render() {
        return (
          <div>
            <div>You clicked {store.state.count} times.</div>
            <div>{store.state.message}</div>
            <button
              onClick={() => {
                const newCounter = store.state.count + 1
                store.state.count = newCounter
                store.state.message = `Current number is ${newCounter}`
              }}
            >Click me</button>
          </div>
        );
      }

    gettersetterに類するものがある様子はなく、store.state[パラメータ]を読んだり上書きしたりするイメージです。

    表示を確認する

    カウンター機能を追加したので、動かしてみましょう。

    スクショを撮り忘れましたが、Click meをクリックすると、メッセージが変わります。

    ストアを使って非同期処理を挟んでみる

    API呼び出しなどの非同期処理が入るケースも試してみました。

    onChangeで「値が変わった時の処理」を設定する

    store.onChangeを使うと、ストア内の値が変更された時に処理を実行できます。

    store.onChange('count', async () => {
      setTimeout(() => {
        store.state.message = `${store.state.message} with ${Math.random()}`
      }, 1000)
    })

    この例では、store.state.countが変更されると、1000ms後にstore.state.messageにランダムな数字を追加します。

    onで特定のイベントを受けて処理を実行する

    setgetに対してイベントを設定することもできます。

    次の例では、apiKey ステートがsetされた時にStripe.jsライブラリを読み込んでいます。

    store.on('set', async(propName) => {
      if (propName === 'apiKey') {
        const value = store.get(propName)
        if (value) {
          const stripe = await loadStripe(value)
          store.set('stripe', stripe)
        } else {
          store.set('stripe', undefined)
        }
      }
    })

    コンポーネント側では、@Props@WatchそしてcomponentDidLoadを利用してAPIキーを渡しています。

    
    export class MyComponent {
      @Prop() apiKey: string;
    
      // <my-component api-key="この値が変更された時の処理">
      @Watch('apiKey')
      updateStripeAPIKey(newValue: string) {
        store.set('apiKey', newValue)
      }
    
      // 初回読み込み時 
      componentDidLoad() {
        this.updateStripeAPIKey(this.apiKey)
      }

    おわりに

    コンポーネントに動きをつけると、どうしてもコードが肥大化してきます。

    そんな時にStoreを使うことで、表示と処理の責務を切り分けることができます。

    Reduxのようなアプリ全体で利用するStoreも便利ですが、軽量なStoreであればコンポーネントの処理を切り出すためにライトに使うのもありかもしれませんね。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark