0
votes

I have no idea what is causing this problem. I am sending request to back end to fetch some data and display it on front. I fetch some recipes from back and store it in array. With v-for i loop trough array and create router-link to navigate to every recipe. Now when i click on some recipe i want to display it details on right side of the screen. When link is clicked i get the right recipe from database and store it in empty object in vuex state. With getters I want to get that object but when i get it it is complitely wrong id.

VUEX MODULE

const state = {
 recipes: [],
 singleRecipe: {}
};

const mutations = {
 'RECIPES_LIST'(state, recipes) {
 state.recipes = recipes;
},
'GET_RECIPE'(state, response) {
 const recipe = response; // THIS IS THE RIGHT RESPONSE 
 state.singleRecipe =  recipe;
 }
}

const actions = {
  initRecipes: ({commit}) => {
  axios.get('http://localhost:3000/recipes')
  .then((response) => {
    commit('RECIPES_LIST', response)
  })
  .catch(err => {
    console.log(err);
  });
  },
  getRecipe: ({commit}, id) => {
   axios.get('http://localhost:3000/recipes/' + id)
  .then(response => {
    const recipe = JSON.stringify(response);
    commit('GET_RECIPE', recipe); // RIGHT RECIPE
  })
  .catch(err => console.log(err));
  },

 const getters = {
 recipes: state => {
 return state.recipes;
 },
  singleRecipe: state => {
   return state.singleRecipe;
  }
};

RECIPE LIST COMPONENT

   <template>
  <div>
    <div class="col-md-6">
      <router-link :to="'/recipes/' + recipe.id"  v-for="recipe in 
 recipes.data">
        <div id="list"  class="panel">
          <div class="panel-body">
            <div class="pull-left">
              <h4>{{recipe.title}}</h4>
            </div>
            <div class="pull-right">
              <img class="img-responsive" :src="recipe.picture" style="width: 80px; height: 80px;">
             </div>
          </div>
        </div>
      </router-link>
    </div>
    <div class="col-md-6">
      <router-view></router-view>
    </div>
  </div>
</template>
<script>
  export default {
    computed: {
      recipes() {
        return this.$store.getters.recipes;
      }
    }
  }
</script>

RECIPE DETAILS COMPONENT

<template>
  <div class="panel" @click="getSingleRecipe">
    <div class="panel-heading">
      <!--<h1>{{recipe.data.title}}</h1>-->
    </div>
    <div class="panel-body">
      <!--<p>{{recipe.data.description}}</p>-->
      <p>Ingredients: </p>
      <ul>
        <li v-for="i in recipe.ingredients">{{i.ingredient}}</li>
      </ul>
      <router-link :to="{name: 'Update', params: {id: id}}"><button class="btn btn-primary">Update Recipe</button></router-link>
      <button class="btn btn-danger" @click="deleteRecipe">Delete Recipe</button>
    </div>
  </div>
</template>
<script>
  import { mapActions } from 'vuex';
  export default {
   data() {
     return {
    id: this.$route.params.id,
    recipe: {}
      }
    },
    watch: {
  '$route' (to, from) {
    this.id = to.params.id;
    this.getSingleRecipe();
        console.log('CHANGEEEEEE' + this.recipe); // GETS RECIPE WITH ID (example 4)
        console.log("ACTIVEEEEEEE ID" + this.id); // GETS RIGHT ID (example id: 2)
      }
    },
   ...mapActions({
      deleteTheRecipe: 'deleteRecipe',
      initRecipes: 'initRecipes',
      getRecipe: 'getRecipe'
      }),
      deleteRecipe() {
    this.deleteTheRecipe(this.id);
    this.initRecipes();
    this.$router.push('/recipes');
  },
      getSingleRecipe() {
         this.getRecipe(this.id);
         this.recipe = this.$store.getters.singleRecipe;
      }
    },
    created() {
      this.getSingleRecipe();
      console.log("CREATED ID" + this.id);
      console.log('CREATEDDDDD ' + JSON.stringify(this.recipe));
    }
  }
</script>
1

1 Answers

0
votes

Try moving your id property from data into a computed property. My guess is once the component has rendered you data.id property is not reacting to the change in route.params.

Another way to load a recipe on route change is to use the beforeEnter function on your router.

import store from '../store'

beforeEnter: (to, from, next) => {
    store.dispatch(getRecipe, to.params.id)
      .then(() => {
        next()
      })
  }

This way you don't have to watch the router in your component. Use mapGetters to get recipe from the store.

computed: {
  ...mapGetters({
    recipe: 'singleRecipe'
  })
}