この記事は 2020年03月16日 のものです。最新の情報はpiniaの公式リポジトリ からご確認ください
- 注意: piniaリポジトリを斜め読みしただけなので大したこと書いていない
- けど vuex だとどうしても不便な場合があるので、 reactive(Vue.observable)によるVanilla State Managementや、 pinia みたいな方法でtype-safeなStoreレイヤーほしいよね.
そんな気持ちの人が増えたらいいよね! 宮ちゃん!
話のコンテキスト
- 今現在 Vue(2.x), vuexを使っているプロジェクトでの利用を想定。
- わりとごりごりしたフロントエンド。 エンドユーザーが触る管理画面 がある
- 複数のvuexモジュールがある。namespaced true. vuexモジュール間でもアクセスしうる。(単方向)
- 徐々にTypescript + compositon-apiを使い始めた。
- actionやgetterの引数や返り値の厳密な型がほしい.........
はて、typescript+composition-api利用している場合、vuex使う理由は?
- 以前からVue.observable()使ったno vuexでのstate managementでもよかった。
- vuexのメリットがあるとすれば、比較的「Vue標準のスタイル」と呼べる. documentも存在するという点だと思う。
(独自の方法でglobal state管理をする場合、プロジェクトローカルな方法をメンバーに伝えて、これに沿って書いてもらう必要はある。) - vuex4でもtypescriptへの注力はあまりなさそうなので、Typescript+CompositionAPI利用時はvuexは選択肢としてかなりモチベーションが低くなる
こんな話もある。
https://speakerdeck.com/ntepluhina/you-might-not-need-vuex
そこで pinia
まだ experimental だけど
Vuex 定義側
src/stores/adminUsersStore.ts
import { createStore } from 'pinia'
export const useAdminUsersStore = createStore({
state: () => ({
usersWithDeleted: [],
}),
getters: {
activeUsers(state, getters) { return state.users.filter((u: User) => !u.retiredAt)
}
action: {
fetchUsers() {
....then((response) => {
this.state.users = response.data.usersWithRetired;
});
}
}
}
利用側
App.vue
<script lang="ts">
import { useAdminUsersStore } = "@/stores/adminUsersStore.ts";
export default defineComponent({ // 旧 createComponent
setup(props, _ctx) {
const adminUsersStore = useAdminUsersStore();
mounted(() => { adminUsersStrore.fetchUsers() })
return {
users: adminUsersStore.activeUsers,
};
}
});
</script>
<template>
<ul>
<li v-for="u in users">{{ u.name }}</li>
</ul>
</template>
いまのところ感じていること
- compositionAPIの
reactive<T>({ ... })
を使って、fooBarStore.ts 内でvanila state管理をおこなっても良いんだけど、createStore({ state, getters, actions })
みたいにある程度 形式が決まっているとメリットがある- チームで開発をする場合、各個人が迷わないかも
- ある程度グルーコードは出てくるだろうから pinia みたいなレイヤーがあると都合がよい。(createStore内部でいろいろやる)
- 例: vanila state management on composition-api の場合違って、piniaの場合、各getters functionごとに computed(() => ... )しなくてよい。
斜め読みしたPinia のmemo
- inject/provide使っていない. export xxx = createStorestore({ ... }) で定義して、 これを直接importして使う。
createStore内部で pinia 内部の管理テーブル(storesMap) にidだけ突っ込んでいる - devtoolサポートやってて偉い。これはちょっとだけ便利かも
疑問点など
- storeYからstoreXのアクセスってどうやるのかまだ調べてない。
storeY = createStore({ ... }) の外側で storeX = useStoreX()
するわけにも行かないし.
https://github.com/posva/pinia#usage
There is one important rule for this to work: the useMainStore (or any other useStore function) must be called inside of deferred functions. This is to allow the Vue Composition API plugin to be installed. Never, ever call useStore like this:
- stateの型かけないの....? (もしくは書かなくてもこまらない? そんなわけないやろ...???)