urql icon indicating copy to clipboard operation
urql copied to clipboard

useSubscription does not respond to reactive variables

Open lsnow99 opened this issue 3 years ago • 1 comments

I am using graphql-code-gen with urql and I am trying to use a subscription to subscribe to events in a room. I don't know the value of roomId during script setup so it needs to be a reactive variable (see code below). I have tried a number of different ways to pass the roomId to useSubscription but none of them seem to respect reactivity. No matter what, the query is only executed once with a roomId of empty string.

I can confirm that roomId.value is undefined on initial page load but is set to a correct value immediately after the first query completes. I can see the id in the template on the app.

<script setup lang="ts">
import {
OnNewMessageDocument,
  useGetRoomByCodeQuery,
  useOnNewMessageSubscription,
} from "@/generated/graphql";
import { useSubscription } from "@urql/vue";
import { computed, ref, watch } from "vue";
import { useRoute } from "vue-router";
import PageWrapper from "../../components/PageWrapper.vue";

const route = useRoute();
const code = route.params["code"] as string;
const shouldPause = ref(true);

const {
  data: roomData,
  error: roomError,
  fetching: roomLoading,
} = useGetRoomByCodeQuery({ variables: { code } });

const room = computed(() => roomData.value?.roomByCode);
const roomId = computed(() => room.value?.id)

const sub1 = useSubscription({
  query: OnNewMessageDocument,
  variables: {
    roomId: roomId.value ?? ""
  }
})
</script>

I even tried to add this but it triggers once when roomId.value updates and just resubscribes with empty string as roomId:

const execute = () => {
  sub1.executeSubscription()
}

watch(roomId, () => {
  console.log('executing')
  execute()
})

lsnow99 avatar Sep 17 '22 17:09 lsnow99

I'm just guessing here, but looking at the place where you actually use the reactive variable you're not actually using a reactive variable, i.e.

const sub1 = useSubscription({
  query: OnNewMessageDocument,
  variables: {
    roomId: roomId.value ?? ""
  }
})

This unwraps roomId.value and hence expects this to be reading out the value just once rather than:

const sub1 = useSubscription({
  query: OnNewMessageDocument,
  variables: {
    roomId: computed(() => roomId.value ?? ""),
  }
})

However, I'm just guessing here... it's also possible you'd rather want to block the request from happening when the variable isn't present, right?

const sub1 = useSubscription({
  query: OnNewMessageDocument,
  variables: {
    roomId,
  },
  isPaused: computed(() => !roomId.value),
})

kitten avatar Sep 21 '22 13:09 kitten

Closing due to inactivity

kitten avatar Oct 13 '22 01:10 kitten