📦

composition-apiにreactiveな引数を渡したいときは関数で渡す

2021/04/06に公開1

タイトルで終わり。以下補足。

こんな感じのcompositionがあったとする。

function useFoo(name: string) {
  return {
    message: computed(() => `Hello ${name}!`)
  }
}

この場合nameはただのstringなのでreactiveではない。
もしreactiveにしたい場合はrefcomputedRedを渡したくなる。

function useFoo(name: Ref<string> | ComputedRef<string>) {
  return {
    message: computed(() => `Hello ${name.value}!`)
  }
}

もちろんこれで期待通り動くが、引数の型定義が冗長気味。もしnamereactive化されたobjectだったりしたらさらに型定義と処理の考慮を追加しないといけない。

詰まるところこのcomposition内では引数がRefComputedRefなのかといったことに関心を持ちたくない。
そんなときはgeneratorを渡してしまえばすっきりする。

function useFoo(getName: () => string) {
  return {
    message: computed(() => `Hello ${getName()}!`)
  }
}

呼び出し側は渡したいデータがRefだろうと何だろうとgeneratorとして渡せばよい。

const name = ref('okada')
useFoo(() => name.value)

関数で渡しておくとwatchなどにそのまま突っ込むこともできて便利。

function useFoo(getName: () => string) {
  watch(getName, () => { ... })
}

値の更新もしたい場合は作法よくsetterを渡す。Refを渡して好き勝手に変更されると何かと面倒が多い。

function useFoo(getName: () => string, setName: (name: string) => void) { ... }

Discussion

edaohedaoh

ComputedRefはRefを継承しているので、Refだけでcomputedも渡せますよ