godisgay
godisgay

Reputation: 11

Passing reactive value from parent to child and accept it in child component

I have an App component, which is a parent component. And two child components, GenreList and GameGrid components. I want to fetch games according to genreId so I'm emitting genreId from GenreList to App component and from that I'm passing genreId to GameGrid component. Right now, I can't seem to accept genreId from GameGrid component. I just started learning Vuejs so can you please point out where I did wrong? Here's my codes.

This is GenreList component. As you can see, I'm emitting genreId to its parent component.

<template>
    <p v-if="error"></p>

    <template v-if="isLoading">
        <ProgressSpinner style="width: 50px; height: 50px;" strokeWidth="6" animationDuration=".7s" aria-label="Loading" />
    </template>

    <ul>
        <li v-for="genre in genres" :key="genre.id" class="py-2">
            <div class="flex gap-2 items-center">
                <img class="w-[36px] rounded-md" :alt="genre.slug" :src="getCroppedImageUrl(genre.image_background)" />
                <p @click="$emit('genreId', genre.id)" class="text-lg cursor-pointer hover:underline">{{ genre.name }}</p>
            </div>
        </li>
    </ul>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import ProgressSpinner from 'primevue/progressspinner'
import axiosClient from '@/services/axiosClient'
import getCroppedImageUrl from '@/libs/CropImage'

const genres = ref([])
const error = ref('')
const isLoading = ref(false)

isLoading.value = true

onMounted(async () => {
    try {
        const res = await axiosClient.get('/genres')
        genres.value = res.data.results
        isLoading.value = false
    } catch (err) {
        error.value = err.message
        isLoading.value = false
    }
})
</script>

This is my App component. From App component, I'm passing selectedGenreId to GameGrid component.

<template>
    <div>
        <div class="p-2">
            <Navbar />
        </div>
        <div class="grid grid-cols-12 mt-5">
            <div class="hidden lg:block col-span-3 pl-3">
                <GenreList @genre-id="handleGenreId"/>
            </div>
            <div class="col-span-12 lg:col-span-9 px-4">
                <GameGrid :selectedGenreId="selectedGenreId" />
            </div>
        </div>
    </div>
</template>

<script setup>
import Navbar from '@/components/NavBar.vue'
import GameGrid from '@/components/GameGrid.vue'
import GenreList from './components/GenreList.vue'

let selectedGenreId = null

function handleGenreId(id) {
    selectedGenreId = id
}

</script>

And I'm accessing selectedGenreId in GameGrid component like this.

<template>
    <p v-if="error">{{ error }}</p>

    <div class="grid grid-cols-12 gap-4">
        <template v-if="isLoading" v-for="skeleton in skeletons" :key="skeleton">
            <div class="col-span-12 lg:col-span-4 md:col-span-6">
                <GameCardSkeleton />
            </div>
        </template>
        <template v-for="game in games" :key="game.id">
            <div class="col-span-12 lg:col-span-4 md:col-span-6">
                <GameCard :game="game" />
            </div>
        </template>
    </div>
</template>

<script setup>
import { ref, onMounted, watch, toRefs } from 'vue'
import axiosClient from '@/services/axiosClient'
import GameCard from './GameCard.vue'
import GameCardSkeleton from './GameCardSkeleton.vue'

const props = defineProps({
    selectedGenreId: Number
})

const games = ref([])
const error = ref('')
const isLoading = ref(false)
const skeletons = [1, 2, 3, 4, 5, 6]

isLoading.value = true

async function fetchGames(genre) {
    try {
        const params = genre ? { genre } : {}
        const res = await axiosClient.get('/games', { params })
        games.value = res.data.results
        isLoading.value = false
    } catch (err) {
        error.value = err.message
        isLoading.value = false
    }
}

onMounted(async () => {
    fetchGames(props.selectedGenreId)
})

watch(props.selectedGenreId, (newGenre) => {
    fetchGames(newGenre)
})
</script>

My expected result is when I first load the page, selectedGenreId will be null. When I select some id from GenreList I want to refetch games according to its genreId. I don't know where I did wrong? Can you please help me?

Upvotes: 0

Views: 131

Answers (0)

Related Questions