vue-a11y / vue-announcer

A simple way with Vue to announce any useful information for screen readers.
MIT License
233 stars 9 forks source link

Using polite / assertive, via composition, inside a watcher #41

Open felixzapata opened 1 year ago

felixzapata commented 1 year ago

Hi, is there any kind of handicap using the announcer, via composition, inside a watcher?

watch(s, (s1) => {
  if (s1 === 0) {
    polite('no sessions found');
  } else {
    polite('found x sessions');
  }
});

I am suffering strange behaviors when I use, for example, the polite function inside a simple watcher after receiving a change. The weird behavior affects the computed properties of other components on the same page; the computed property is regenerated repeatedly (it looks like the polite is forcing some kind of render).

I do not know yet what is the root problem but what I know is if I remove the polite calling inside the watcher, the strange behaviors disappear.

felixzapata commented 1 year ago

I think the problem is more related to calling the polite method inside a computed property callback when you have more than one component on the same page.

For example:

<script setup lang="ts">
import TheWelcome from '../components/TheWelcome.vue'
import OneMore from '../components/OneMore.vue'
</script>

<template>
  <main>
    <TheWelcome />
    <OneMore />
  </main>
</template>
<script setup lang="ts">
import { ref, computed } from "vue";
import { useAnnouncer } from '@vue-a11y/announcer';
const { polite } = useAnnouncer();
const message = ref("");

const filteredUsers = computed(() => {
  console.log('filtered')
  polite('foobar');
  return [];
});

</script>

<template>
  {{filteredUsers}}
  </template>
<script setup lang="ts">
import { ref, watch } from "vue";
import { useAnnouncer } from '@vue-a11y/announcer';
const { polite } = useAnnouncer();

function foobar() {
  polite('foobar');
}

</script>

<template>
  <button @click="foobar">Button</button>
</template>

Quoting the Vue documentation: don't make async requests or mutate the DOM inside a computed getter!, I assume that the DOM change created by the polite method should kind of create a side effect. In this case, the word filtered appears every time the button is clicked.