1
votes

I am creating movie-app with Vue and Vuex which will display all movies in Home component and on click single movie in Details (child) component. I get all movies in Home component but I can not display single movie in Details component.

I have enabled props in child component but I have problem with passing movie ID to method imported from getters (in Details component) which should filter selected movie from movies list.

Home component

<template>
  <div class="home">
     <router-view />
          <h1>Home component:</h1>
            <div v-for="movie in movies"
              :key="movie.id">
              <div>
                <router-link :to="'/movie/' + movie.id">{{ movie.title }}</router-link>
              </div>
            </div>
  </div><!--home-->
</template>

<script>
import axios from 'axios'
import { mapGetters, mapActions } from 'vuex'

export default {
  name: "home",
  methods: {
        ...mapActions(['fetchMovies']),
    },
    computed: {
        ...mapGetters(['movies'])
    },
    created() {
        this.fetchMovies()
    }
};
</script>

Details component

<template>
    <div>
        <h1>Movie details - child component</h1>
        <h2>Title: {{ movie.title }}</h2>
    </div>
</template>

<script>
import { mapGetters } from 'vuex'
    export default {
        props: ['id'],
        computed: {
            movie() {
                return this.$store.getters.singleMovie(this.id)
            }
        }
    }
</script>

Vuex store

const state = {
  movies: []
};
const getters = {
  movies: state => state.movies,
  singleMovie: state => movieId => {
    return state.movies.find(item => item.id === movieId);
  }
};
const actions = {
  async fetchMovies({ commit }) {
    const response = await axios.get(
      movie_url + "movie/popular" + "?api_key=" + api_key
    );
    commit("setMovies", response.data.results);
  }
};
const mutations = {
  setMovies: (state, items) => (state.movies = items)
};
export default {
  state,
  getters,
  actions,
  mutations
};

I tried to replace {{movie.title}} with {{id}} and then I get displayed movie ID as I click on listed movies in Home component. I also tried to hard code movie id as parameter: return this.$store.getters.singleMovie(299536) and I successfully get title displayed but in console I get error "TypeError: Cannot read property 'title' of undefined". Obviously I am making mistake with passing delivered movie ID.

1

1 Answers

0
votes

Your computed property movie is not loaded in every vue life cycle. So, in the first time you get movie, it is undefined and your mustache {{ movie.title }} is actually something like {{ 'undefined'.title }}, which causes the error.

To solve it, you can both add a v-if="movie" conditional in template or return a default value in computed property movie. Like this, for example: return state.movies.find(item => item.id === movieId) || {};