Vue’s Composition API wraps reactive state in a Ref object through functions such as ref(), computed(),
toRef(), customRef(), shallowRef(), toRefs(), or defineModel(). A Ref is
a plain object with a single value property; reading or writing that property is what triggers Vue’s reactivity.
A Ref object can be used directly as an operand: in a comparison, an arithmetic or increment expression, a template literal, a
condition, or an assignment. Doing so operates on the Ref object itself instead of the value it wraps. Because a Ref object
is always truthy, conditions such as if (count) are always true regardless of the underlying value. Arithmetic and string operations
produce results based on the object rather than the wrapped number or string, and assigning a new value to the identifier replaces the reactive
binding instead of updating the state that Vue tracks.
This pattern has no legitimate use: fix it by accessing or updating the wrapped value through .value.
<script setup>
import { ref } from 'vue';
const count = ref(0);
function increment() {
count++; // Noncompliant: "count" is a ref; use "count.value++" instead
}
</script>
<script setup>
import { ref } from 'vue';
const count = ref(0);
function increment() {
count.value++;
}
</script>
<script setup>
import { computed, ref } from 'vue';
const items = ref([]);
const hasItems = computed(() => items.value.length > 0);
function checkout() {
if (hasItems) { // Noncompliant: "hasItems" is a ref; use "hasItems.value" instead
items.value = [];
}
}
</script>
<script setup>
import { computed, ref } from 'vue';
const items = ref([]);
const hasItems = computed(() => items.value.length > 0);
function checkout() {
if (hasItems.value) {
items.value = [];
}
}
</script>
ref()