概要
まだまだVue.jsの理解も浅い中で、コンポーネント分割していたらロジックが複雑になってしまい、状態管理にPiniaを使うことにしました。
$subscribe
によるState監視で意図しない動きをしてしまっていたので、メモです。そもそもこのようなPiniaの使い方がよくない可能性がありますが、、、
状況
Piniaで2つのStore(StoreA, StoreB)を利用しており、StoreAにはオブジェクト情報、StoreBにはオブジェクトのリスト情報を保持していました。
状況によって、StoreAの中にStoreBのリスト内のオブジェクトを保持するケースがありました。
import { defineStore } from 'pinia'
export const useStoreA = defineStore({
id: 'storea',
state: () => ({
obj: {}
}),
getters: {
// ...省略
},
actions: {
updateObj(obj) {
this.obj = obj
},
// ...省略
}
})
import { defineStore } from 'pinia'
export const useStoreB = defineStore({
id: 'storeb',
state: () => ({
Array: []
}),
getters: {
getObjById: (state) => (id: string) => {
return state.obj.find((obj) => obj.id == id)
}
},
actions: {
// ...省略
}
})
起きたこと
storeBから取得したオブジェクトをそのままstoreAに更新かけました。
const storeA = useStoreA()
const storeB = useStoreB()
const obj = storeB.getById(3)
storeA.updateObj(obj)
別のところで$subscribe
を設定し、storeBのstateを監視していました。
すると、storeAのstateが更新された際に、storeBの$subscribe
アクションが動いてしまいました。
解決策
getしてきたstoreBの参照を渡してしまっていることが原因だと思います。
このまま渡すのであれば、オブジェクトのディープコピーを渡すことで正しく動きました。
ディープコピーはObject.assign(), JSON.parse(), JSON.stringfy()を組み合わせて作成します。
const storeA = useStoreA()
const storeB = useStoreB()
const obj = storeB.getById(3)
storeA.updateObj(Object.assign({}, JSON.parse(JSON.stringify(obj))))