I'm working on implementing a "like" or "add to favorite" feature in VUE 3. However, I'm facing an issue where the UI doesn't update when I like or unlike something. It only refreshes properly. I'm using backend functions for liking and disliking, which are functioning correctly. Can anyone help me with this?
Here is the code of the Parent component:
<Suspense>
<template #default>
<div class="is-flex is-1 is-flex-wrap-wrap" v-if="recipes">
<RecipeCard
class="card radius-small mx-2 my-3 p-3"
v-for="(recipe, i) in recipes"
:recipe="recipe"
:key="i"
:savedDishesId="savedRecipesIds"
@openRecipe="openFunc(recipe)"
@likeIndividual="isLiked(recipe)"
>
</RecipeCard>
</div>
</template>
</Suspense>
import RecipeCard from '../components/recipe-cards/recipeCard.vue'
const recipeStore = useRecipeStore(),
userStore = useUserStore(),
loginStore = useLoginStore(),
router = useRouter()
const recipes = ref([]),
username = ref('User'),
savedRecipesIds = ref([])
onMounted(async () => {
fetchData()
let userId = VueCookies.get('id')
if (userId) {
let user = await userStore.fetchAccDetails(VueCookies.get('id'))
username.value = user.username
}
savedRecipesIds.value = await userStore.fetchSavedDishesId(userId)
console.log(savedRecipesIds.value)
})
async function isLiked(userId) {
console.log("parent");
savedRecipesIds.value = await userStore.fetchSavedDishesId(userId)
}
async function fetchData() {
recipes.value = await recipeStore.getRecipes()
}
console.log(loginStore.isAuth())
function openFunc(recipe) {
router.push({ path: `/recipe/${recipe._id}` })
}
</script>
THE CHILD COMPONENT:
<template>
<div class="recipe-card bg-color-white" style="cursor: pointer">
<div class="card-head" @click="emits('openRecipe')">
<figure class="">
<img :src="props.recipe.img" alt="Recipe Image" class="image radius-default" />
</figure>
</div>
<div class="card-desc" @click="emits('openRecipe')">
<h3 class="is-size-3 color-tx-sec">{{ props.recipe.dish_name }}</h3>
<p class="is-size-5">{{ resizeText(props.recipe.description) + '...' }}</p>
</div>
<div class="is-flex is-justify-content-space-between is-align-items-center is- mt-3">
<p class="has-text-link" @click="emits('openRecipe')">View more</p>
<Icon
icon="ph:heart-bold"
v-if="!isLiked"
style="height: 2rem; width: 2rem"
@click="toggleLike()"
></Icon>
<Icon
icon="mdi:heart"
color="red"
v-else
style="height: 2rem; width: 2rem"
@click="toggleLike()"
></Icon>
</div>
</div>
</template>
<script setup>
import { Icon } from '@iconify/vue'
import { computed, onMounted, ref, watch } from 'vue'
import { useUserStore } from '../../stores/userStore'
import VueCookies from 'vue-cookies'
const isLiked = ref(false)
onMounted(() => {
updateLikeStats()
})
watch(
() => props.savedRecipesIds,
() => {
updateLikeStats()
}
)
const userStore = useUserStore(),
userId = ref(VueCookies.get('id') || null)
const emits = defineEmits(['openRecipe', 'likeIndividual'])
const props = defineProps({
recipe: {
type: Object,
required: true
},
savedRecipesIds: {
type: Array,
required: true,
default: () => []
})
// Function for resizing the description
function resizeText(text) {
return text.slice(0, 120)
}
async function toggleLike() {
await userStore.toggleLikeRecipe(props.recipe._id, { userId: userId.value })
emits('likeIndividual', userId.value);
updateLikeStats()
}
function updateLikeStats() {
isLiked.value = props.savedRecipesIds.includes(props.recipe._id)
console.log(isLiked.value)
}
</script>