State not changing when using a composables
Hello, my component was not updating when I changed player id using a composables when I placed this directly in component it was working but as composables it wasn't:
import { ref, computed } from 'vue';
import { throws } from '~/data/baseball';
export function usePlayerData(players, playerId) {
const selectedPlayer = computed(() => {
if (playerId === null) {
return null;
}
return players.find((player) => player.id == playerId);
});
const selectedThrows = computed(() => {
if (selectedPlayer.value === null) {
return null;
}
return throws.filter((shot) => shot.player_id === selectedPlayer.value.id);
});
return { selectedPlayer, selectedThrows };
}
So this is now my composables and in my component:
const props = defineProps({
playerId: {
required: true,
},
});
const { value: players } = useState('players');
const { selectedPlayer, selectedThrows } = usePlayerData(
players,
props.playerId
);
This was not working anyone knows why?
This works tho:
Composables:
import { ref, computed } from 'vue';
import { throws } from '~/data/baseball';
export function usePlayerData(players, playerId) {
const selectedPlayer = computed(() => {
if (playerId.value === null) {
return null;
}
return players.find((player) => player.id == playerId.value);
});
const selectedThrows = computed(() => {
if (selectedPlayer.value === null) {
return null;
}
return throws.filter((shot) => shot.player_id === selectedPlayer.value.id);
});
return { selectedPlayer, selectedThrows };
}
Component:
const props = defineProps({
playerId: {
required: true,
},
});
const reactivePlayerId = ref(props.playerId);
watch(
() => props.playerId,
(newPlayerId) => {
reactivePlayerId.value = newPlayerId;
}
);
const { selectedPlayer, selectedThrows } = usePlayerData(
players,
reactivePlayerId
);
I used a watch for my ref
9 Replies
Does anyone can explain why the old one does not work and why the new one works and if there is a better way to do so
You don't have to use a ref at all. Props are already reactive, just use
props.playerId
where you need itdoes not work, as I showed in the first solution
Your code in the post is hard to read because it's all just text.
What is it you're trying to achieve? And does it also not work in a reproduction?
I don't see why a reactive prop wouldn't work
would be better to format that code 🙂
Wait, even if props are reactive, not every value in props is reactive.
So if you pass
props.playerId
to a composable, the value of it within the composable is not reactive anymore.
If props.playerId change within the component, the composable still keeps the old value, so the watcher in your composable:
will not trigger, since only the props
is reactive, not the props.playerId
itself. So if you pass const foo = myComposable(props.playerId)
you do not get the changes.
You need to pass actually a ref
/ computed
or the whole props object to keep the reactivity across your component and composable.
So:
Would work, while
will not.Legend.
Thank you for the explanation!
Why passing the whole props object does not work to my composables?
UsePlayerData(props)
Works for me.
Uhm ok