Subscribe on changes!

When use Composition setup and not deconstruct useXX return object, the computeRef need .value at template

avatar
Feb 27th 2023

Vue version

3.2.21

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-oanufe?file=src/App.vue

Steps to reproduce

create ./test.ts

import { shallowReactive, computed } from "vue";
export const useTest = () => {
  const list = [
    { id: 1, name: "1" },
    { id: 2, name: "2" },
  ];
  const disables = shallowReactive(new Set([1]));
  return {
    okList: computed(() => {
      return list.filter((e) => !disables.has(e.id));
    }),
  };
};

use it with two way at App.vue

<script setup>
import { useTest } from './test';
const test = useTest();
const { okList } = useTest();
</script>

<template>
  <div v-for="el in test.okList">   
    {{ el.name }}  -- not ok line
  </div>
  <div v-for="el in test.okList.value">
    {{ el.name }}
  </div>
  <div class="deconstructed" v-for="el in okList">
    {{ el.name }}
  </div>
</template>

What is expected?

expect can use test.okList directly at template without .value

<div v-for="el in test.okList">   
    {{ el.name }}  --should work
  </div>

What is actually happening?

need .value to read the value as following, really wierd:

  <div v-for="el in test.okList.value">
    {{ el.name }} -- 
  </div>

System Info

--

Any additional comments?

No response

avatar
Feb 27th 2023

and looks like when compute is a boolean or number ref, it works as expected, but when it's an array , it broke

avatar
Feb 27th 2023

I dont see a bug. The composable returns a non-reactive object, whose properties are not unwrapped in the template. While I'm aware this can trip people up, this is documented, expwcted behavior

avatar
Feb 27th 2023

@LinusBorg This is because test.okList is compiled to unref(test).okList, I feel it should be unref(test.okList).

avatar
Feb 27th 2023

This is explicitly documented behavior so changing it would be a breaking change that would break existing apps all over the place. So it won't happen (until we want to talk about Vue 4 maybe, some day).

avatar
Feb 27th 2023

Agreed.

avatar
Feb 27th 2023

ok ok, thanks for explain - hope some day this inconsistency will disappear

but really strange, documented , so I worked around it, just a guess and it worked: This case just a getter, not {{test.okList + 1}} o.