reactiveな変数を更新後に参照するwatchを絶対にトリガーしたい

# 概要
- タイトル通りのことをやろうとしてハマったのでメモする
- 正しい実装かわからんので誰か教えてほしい

# やりたかったこと

- ComponentA、ComponentBがいて、ComponentAのアクションをComponentBに反映したかった
    - 具体はComponentAでボタンを押したら、ComponentBのフォームの内容を変更するという処理
- 割と階層が離れている → provide/injectを利用した
    - Composableを用意して、reactiveを管理するstateとupdate関数を用意して、provideする
    - stateはreadonlyで返した
- さっと作ったら問題があった
    - 例えばComponentAでアクションしてComponentBのフォームを更新した場合、ComponentBはreadonlyなreactive変数を受け取るので、そのままv-modelにわたすと、変更できないフォームが完成する
    - それは困るので、ComponentBでは、Composableからreadonlyの変数を受取り、watchするようにして、トリガーされたら、ComponentBのreactiveな変数を更新するようにした
        - これはよかったが、同様にComponentAで操作後、ComponentBのフォームを更新した後、ComponentBのフォームを手動で書き換えると、ComponentAでもっかい同じボタンを推押すと、AのState自体は変更がないため、伝播せずwatchがトリガーされない。ということが発生した


コードはこんな感じ

```typescript:useFormState.ts
interface FormState {
  inputValue: Readonly<Ref<string>>
  updateInputValue: (value: string) => void
}

export const FormStateSymbol: InjectionKey<FormState> = Symbol('FormState')

/**
 * provide
 */
export function provideFormState () {
  const inputValue = ref<string>('')

  const updateInputValue = (value: string): void => {
    inputValue.value = value
  }

  const formState = {
    inputValue: readonly(inputValue),
    updateInputValue
  }

  provide(FormStateSymbol, formState)

  return formState
}

/**
 * inject
 */
export function useFormState (): FormState {
  const formState = inject(FormStateSymbol)
  if (!formState) {
    throw new Error('Form state not provided')
  }
  return formState
}
```

```vue:ComponentA.vue
<template>
    <button :click="setInputValue('hogehoge')">ボタン</button>
</template>

<script setup>
const { updateInputValue } = useFormState()

const setInputValue = (inputValue: string) => {
  updateInputValue(inputValue)
}
</script>
```

```vue:ComponentB.vue
<template>
      <input
        type="text"
        v-model="inputValue"
        placeholder="ほげほげ"
      >
</template>

<script setup>
const inputValue = ref('')
const { inputValue: otherInputValue } = useFormState()

// ここが動かないので困っている
watch(otherInputValue, (value: string) => {
  inputValue.value = value
})

</script>
```


ComponentAとComponentBの親Componentでprovideしています

```javascript
provideFormState()
```

# バージョン等

- Vue3.5
- Nuxt3.13.1


# 結論どうしたか


泣く泣く
 別のreactive変数を用意して、そいつは必ず変更するようにしました


```diff_typescript:useFormState.ts
interface FormState {
  inputValue: Readonly<Ref<string>>
+ inputValueChanged: Readonly<Ref<number>>
  updateInputValue: (value: string) => void
}

export const FormStateSymbol: InjectionKey<FormState> = Symbol('FormState')

/**
 * provide
 */
export function provideFormState () {
  const inputValue = ref<string>('')
+ const inputValueChanged = ref<number>(0)

  const updateInputValue = (value: string): void => {
    inputValue.value = value
+   inputValueChanged.value++
  }

  const formState = {
    inputValue: readonly(inputValue),
    updateInputValue
  }

  provide(FormStateSymbol, formState)

  return formState
}

/**
 * inject
 */
export function useFormState (): FormState {
  const formState = inject(FormStateSymbol)
  if (!formState) {
    throw new Error('Form state not provided')
  }
  return formState
}
```

```diff_vue:ComponentB.vue
<script setup>
+ const { inputValue: otherInputValue, inputValueChanged } = useFormState()

// inputValueChangedが必ず更新されるのでトリガーされる
+ watch([otherInputValue, inputValueChanged], ([value, _]: [string, number]) => {
  inputValue.value = value
})
</script>
```


# 色々試したこと

- triggerRef
    - https://ja.vuejs.org/api/reactivity-advanced#triggerref
    - よくわからないが動作しなかった
- CustomRef
    - これもだめ
- `watch(() => xxx.value, { flush: 'sync' })` とかにしてみる
    - これもだめ


# 雑感

本当にこれでよいかわからないので誰か教えてください！（他力本願）