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>
);
}
getter
やsetter
に類するものがある様子はなく、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
で特定のイベントを受けて処理を実行する
set
やget
に対してイベントを設定することもできます。
次の例では、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であればコンポーネントの処理を切り出すためにライトに使うのもありかもしれませんね。