Nuxt2+TypeScript+Composition APIで provide/inject

状態とロジックを切り出す

/composables/useModal.ts

import { reactive, InjectionKey, computed, watch } from "@nuxtjs/composition-api";
export default function useModal() {
  const isCalled = ref(false)
  const modalState = reactive<{
    isOpen: boolean;
  }>({
    isOpen: false
  })

  // computed もそのまま持っていける
  const view_text = computed(()=>{
    return modalState.isOpen ? 'オープンです':'クローズです'
  })
  const openModal = () => {
    modalState.isOpen = true;
  }
  const closeModal  = () => {
    modalState.isOpen = false;
  }
  // watch もいける
  wacth(
    isCalled,
    (current) => {
      // 処理
    }
  )
  return {
    modalState,
    openModal,
    closeModal,
    view_text 
  }
}

export type ModalStore = ReturnType<typeof useModal>
export const ModalKey: InjectionKey<ModalStore> = Symbol('ModalStore');

provide

適当なcomponent内で

import { defineComponent, provide } from "@nuxtjs/composition-api";
import useModal, {ModalKey} from "@/composables/useModal"
export default defineComponent({
  setup(props) {
    provide(ModalKey, useModal())
  },
});

inject

provideしたコンポーネント以下で

import {defineComponent, inject} from '@nuxtjs/composition-api'
import {ModalStore, ModalKey} from "@/composables/useModal"
export default defineComponent({
  setup(props){
    const { modalState, openModal, view_text } = inject(ModalKey) as ModalStore
    // as ModalStore してしまっているので、 undefinedはあり得ないとしているね…
    return {openModal, modalState, view_text }
  }
})

inject で受け取る ref, reactive, computed の値の挙動確認

// composables 側
export default function useHoge() {
  const refVal = ref(3)
  const computedVal = computed(()=>refVal.value)
  const refObj = ref({
    aa:'aaa'
  })
  const computedRefObj = computed(()=>_.cloneDeep(refObj.value))
  const reacitveObj = reactive({
    aa:'bbb'
  })
  const computedReacitveObj = computed(()=>_.cloneDeep(reacitveObj))
  return {refVal, computedVal, refObj, computedRefObj, reacitveObj}
}

// inject された側
const { refVal, computedVal, view_text } = inject(HogeKey) as HogeStore
revVal.value = 2 // 代入できる
computedVal.value = 2 // readonly のエラーがでて代入できない
refObj.value.aa = 'hoge' // 代入できる
computedRefObj.value = {aa:'hoge'} // readonly のエラーがでて代入できない
computedRefObj.value.aa = 'hoge' // 代入できるが一時的
reacitveObj.aa = 'hoge' // 代入できる
computedReacitveObj.value.aa = 'hoge' // 代入できるが一時的

 

リアクティブが損なわれる例

// composables 側
export default function useHoge() {
  const refObj = ref({
    aa:'aaa'
  })
  const reacitveObj = reactive({
    aaa:'bbb'
  })
  return {...refObj.value, ...reacitveObj } // ref の値は valueにいる
}

// inject された側
const { aa, aaa } = inject(HogeKey) as HogeStore
// aa , aaa いずれもただの値で、すでにリアクティブではない

inject 関係ないけど リアクティブが損なわれる例

const refObj = ref({ aa:'aaa' })
const reacitveObj = reactive({
  aaa:'bbb'
})
const {aa} = refObj.value
const {aaa} = reacitveObj

// reactive は toRefs を通してあげることでリアクティブになる
const {aaa} = toRefs(reacitveObj)