Home > Enterprise >  How to pass reactive data to a composable in Vue 3
How to pass reactive data to a composable in Vue 3

Time:01-26

Is it possible to declare a reactive object in Vue, and then pass members of that object to a composable while retaining reactivity?

For example:

I declare a "State" type:

type State = { myObjectList: Array<MyObject> }

Then in my component I initialize my state:

const state = reactive<State>{( myObjectList: new Array<MyObject>() )}

Where state.myObjectList gets populated via API call on component mount

My question is, is it possible to pass around state.myObjectList to a composable, and have that composable be aware of changes made to elements inside of state.myObjectList?

i.e. to have a composable like:

export default function useSimpleCalculator(list: Array<MyObject>){

  const dynamicSumValue = computed(():number => { 
    let sum = 0;
    list.forEach(el => {  sum  = el.someValueThatChanges });
    return sum;
  });

 return { dynamicSumValue }

}

then use that composable like:

const {dynamicSumValue} = useSimpleCalculator(state.myObjectList);

and have dynamicSumValue be updated as changes are made to elements inside state.myObjectList

I've tried to implement like the above, but when I pass any property that was on the state object, it loses its reactivity inside the composable.

Passing refs to the composable seems to work ( i.e. const val = ref(2) ), but that goes against the pattern our team decided on for component-wide state data

Any insight would be helpful

CodePudding user response:

As you've discovered, you cannot pass properties of a reactive object to a function and maintain reactivity for that property. This comes up often for props as well, which are just a reactive object like 'state' in your example. You'll need to convert your state to refs and pass a ref for reactivity to work properly:

useSimpleCalculator(toRef(state, 'myObjectList'));

or

const { myObjectList } = toRefs(state);
useSimpleCalculator(myObjectList)

will both work

CodePudding user response:

Refs are specifically used for cases when a value needs to be passed by reference (hence the name).

Since list is not supposed to be modified, it can be just a computed ref:

const myObjectList = computed(() => state.myObjectList);
useSimpleCalculator(myObjectList);

and

function useSimpleCalculator(list: Ref<Array<MyObject>> | ComputedRef<Array<MyObject>>){...}
  •  Tags:  
  • Related