Pinia의 state와 Firestore를 간단히 동기화하는 pinia-plugen-firestore sync

이미 다 했으니 제가 소개해 드릴게요!
npm
https://www.npmjs.com/package/pinia-plugin-firestore-sync
창고는 여기 있습니다(🌟선물받을 수 있으면 기쁘겠다!
https://github.com/kazuooooo/pinia-plugin-firestore-sync

모티프


PiniaFirestore 두 개는 개발 효율을 대폭 높일 수 있는 우수한 라이브러리와 데이터베이스이지만 Pinia의state와Firestore의 문서를 동기화하려면 onSnapShot를 사용해야 한다.

export const useExampleStore = defineStore('expamle', {
  state: {/*...*/}
  actions: {
    async setup() {
      // ...
      //🌟 docDataとdocRefを同期
      onSnapshot(docRef, (ds) => {
        if (ds.exists()) {
          this.$patch({ docData: ds.data() })
        }
      })
    }
  }
})
이것onSnapshot은 개발된 것과 같은 처리를 여러 곳에서 여러 번 써야 하기 때문에 더 이상 DRY가 아니다.
또 하나의 스토어에서 여러 개의 Doctoment와 동기화하려면 세로로 몇 번 써야 한다. 너무 지루하고 전망도 나쁘다.
단순히 피니아의 스테이트와 파이어스토어의 문서를 동기화하고 싶었을 뿐인데 내부에 대한 자세한 사정을 너무 많이 알고 있어 역겹다.
async setup() {
  // 何回もonSnapshotを書く必要があり、めちゃくちゃ冗長に😱
  onSnapshot(docRefA, (ds) => {
    if (ds.exists()) {
      this.$patch({ docDataA: ds.data() })
    }
  })
  onSnapshot(docRefB, (ds) => {
    if (ds.exists()) {
      this.$patch({ docDataB: ds.data() })
    }
  })
  onSnapshot(docRefC, (ds) => {
    if (ds.exists()) {
      this.$patch({ docDataC: ds.data() })
    }
  })
}
그래서 이 문제를 해결하기 위해 만들었다pinia-plugin-firestore-sync.
이 플러그인을 사용하면 방금 전의 코드가 매우 간단해질 것입니다.스케줄러🙌)
async setup() {
  // やったね🙌
  this.sync('docDataA', docRefA)
  this.sync('docDataB', docRefB)
  this.sync('docDataC', docRefC)
}

사용법


README에도 같은 기록이 있는데 여기도 일본어로 소개합니다.
플러그인 먼저 설치
npm install pinia-plugin-firestore-sync
use를 사용하여 플러그 인을 추가합니다.
import { PiniaFirestoreSync } from 'pinia-plugin-firestore-sync'

// プラグインを追加
const pinia = createPinia().use(firestoreSyncPlugin)
app.use(pinia).mount('#app')

문서와 동기화할 때


동기화하려는 Pinia의 속성 이름을 첫 번째 매개변수에, Docoment Reference를 두 번째 매개변수에 각각 지정하여 쉽게 동기화할 수 있습니다.
this.sync(
  'docData', // Document Dataと同期させたいpiniaのプロパティ名
   docRef    // Document Reference
)
샘플 코드
import { doc, getFirestore } from "firebase/firestore"
import { defineStore } from "pinia"

type ExampleDoc = {
  name: string,
  age: number
}

export type State = {
  docData: ExampleDoc | null,
}

export const useExampleStore = defineStore('expamle', {
  state: (): State => {
    return {
      docData: null,
    }
  },
  actions: {
    async setup() {
      // Get Document reference
      const store = getFirestore()
      const docRef = doc(store, 'Examples/id')

      // Do the magic
      this.sync('docData', docRef)
    }
  }
})

모음과 동기화할 때


모음을 동기화할 수도 있습니다.
이 또한 동기화하려는 Pinia의 속성 이름을 첫 번째 매개변수에, Collection Reference를 두 번째 매개변수에 지정할 뿐입니다.간단하네요!
this.sync(
  'collectionData' // Collection Dataと同期させたいpiniaのプロパティ名
   collectionRef   // Collection Reference
)
샘플 코드
import { collection, getFirestore } from "firebase/firestore"
import { defineStore } from "pinia"

type ExampleDoc = {
  name: string,
  age: number
}

export type State = {
  collectionData: ExampleDoc[] | null,
}
export const useExampleStore = defineStore('expamle', {
  state: (): State => {
    return {
      collectionData: null,
    }
  },
  actions: {
    async setup() {
      // Get Collection reference
      const store = getFirestore()
      const collectionRef = collection(store, 'Examples')

      // Do the magic
      this.sync('collectionData', collectionRef)
    }
  }
})

질의와 동기화할 때


질의를 동기화할 수도 있습니다.
나는 네가 이미 알고 있다고 생각한다. 단지 동기화하고 싶은 Pinia의 속성 이름을 첫 번째 파라미터에 맡기고, Collection Reference는 두 번째 파라미터에 맡길 뿐이다.예상대로 웃네요.
this.sync(
  'queryData' // Collection Dataと同期させたいpiniaのプロパティ名
   query      // Query
)
샘플 코드
import { collection, getFirestore, query, where } from "firebase/firestore"
import { defineStore } from "pinia"

type ExampleDoc = {
  name: string,
  age: number
}
export type State = {
  queryData: ExampleDoc[] | null,
}
export const useExampleStore = defineStore('expamle', {
  state: (): State => {
    return {
      queryData: null,
    }
  },
  actions: {
    async setup() {
      // Build query
      const store = getFirestore()
      const collectionRef = collection(store, 'Examples')
      const q = query(collectionRef, where('name', '==', 'wombat'))

      // Do the magic
      this.sync('queryData', q)
    }
  }
})

내부 구조


내부 구조에 신경 쓰는 분들도 계실 것 같아서 간단하게 소개해 드리겠습니다.
우선, Pinia는 다음과 같은 방법플러그 인을 통해 스토어에서 공통된 방법과 속성을 간단하게 생성할 수 있다.
import { PiniaPluginContext } from "pinia";

// プラグイン
const magicNumPlugin = ({ store }: PiniaPluginContext) => {
  store.magicNumber = 5
}

// 型付
declare module 'pinia' {
  export interface PiniaCustomProperties {
    magicNumber: number
  }
  export interface DefineStoreOptionsBase<S, Store> {
}
이 구조를 이용하여 성장sync.
30줄 정도의 아주 짧은 코드.
import { CollectionReference, DocumentReference, onSnapshot, Query, Unsubscribe } from "firebase/firestore";
import { PiniaPluginContext } from "pinia";

export const PiniaFirestoreSync = ({ store }: PiniaPluginContext) => {
  store.sync = (key, ref) => {
    // Document
    if (ref instanceof DocumentReference) {
      return onSnapshot(ref, (ds) => {
        if (ds.exists()) {
          store.$patch({ [key]: ds.data() })
        }
      })
    }

    // Collection or Query
    return onSnapshot(ref, (qs) => {
      const datum = qs.docs.map(d => d.data())
      store.$patch((state) => {
        state[key] = datum
      })
    })
  }
}

declare module 'pinia' {
  export interface PiniaCustomProperties<Id, S, G, A> {
    sync(key: string, ref: DocumentReference): Unsubscribe
    sync(key: string, ref: CollectionReference): Unsubscribe
    sync(key: string, ref: Query): Unsubscribe
  }
}
onSnapShot과 같은 방법명으로 Doocument/Collection/Query를 모두 납품하고자 하기 때문에 납품의 유형에 따라 내부에if분할을 진행한다.
store.sync = (key, ref) => {
  // Document
  if (ref instanceof DocumentReference) {
    return onSnapshot(ref, (ds) => {
      if (ds.exists()) {
        store.$patch({ [key]: ds.data() })
      }
    })
  }

  // Collection or Query
  return onSnapshot(ref, (qs) => {
    const datum = qs.docs.map(d => d.data())
    store.$patch((state) => {
      state[key] = datum
    })
  })
}
그런 다음 인터페이스에 전달될 수 있는 유형을 Overload 형식으로 정의합니다.
declare module 'pinia' {
  export interface PiniaCustomProperties<Id, S, G, A> {
    sync(key: string, ref: DocumentReference): Unsubscribe
    sync(key: string, ref: CollectionReference): Unsubscribe
    sync(key: string, ref: Query): Unsubscribe
  }
}
string을 State의 속성에 한정하고 싶은데 어떻게 하는지 모르겠어요. 아시는 분 있으면 알려주세요.🙏
이상, pinia의 플러그인은 아직 공개되지 않았습니다. 여러분도 도전해 보세요!

좋은 웹페이지 즐겨찾기