👀

【Vue3】watch内でリスナー解除時にReferenceErrorが出た時の対処法

2022/01/03に公開

Vue.jsのwatchを利用している際に、以下エラーが出た時の対処法です。

ReferenceError: Cannot access 'unwatch' before initialization

概要

watchを利用している際に、watch内でリスナーを解除したい時があると思います。
例えば以下のようにユーザ情報を監視して、undefinedからユーザ情報が格納されたタイミング(ユーザ情報を参照可能になったタイミング)で、何かしらの処理を一度だけ実行したい場合があります。

Sample.vue
const unwatch = watch(user, () => {
  const userId = user.value?.uid;
  if (!userId) return;

  // ユーザIDを用いた何かしらの処理

  // リスナー解除
  unwatch();
  },
  {
    immediate: true, // 構文解析時に実行
  }
);

上記コードを実行すると、以下のようなエラーメッセージが表示されます。

ReferenceError: Cannot access 'unwatch' before initialization

これはwatchのオプションにimmediate: trueを指定した状態で、watch内でリスナー解除をしようとすると発生するエラーです。

解決方法

上記エラーを解決するためには、以下のようにします。

  1. watchの戻り値を受け取った際に変数宣言するのではなく、事前に変数を宣言しておく
  2. watch内でunwatchする際に、リスナー解除関数が格納されていることを確認してから実行する
Sample.vue
// ReferenceErrorにならないために宣言
let unwatch = null;
unwatch = watch(user, () => {
  const userId = user.value?.uid;
  if (!userId) return;

  // ユーザIDを用いた何かしらの処理

  // unwatchが参照可能な場合に、リスナー解除
  // これをやらないとunwatchにリスナー解除関数が格納される前に実行されるので、
  // 関数ではありませんというエラーが発生します。
  if(unwatch) unwatch();
  },
  {
    immediate: true, // 構文解析時に実行
  }
);

Discussion