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>>){...}
