Vuex Store返回值异常:获取单条Recipe时ID错误求助
Alright, let's figure out why you're getting the wrong ID when fetching your single recipe—there are a few key issues in your code causing this. Let's fix them one by one:
1. You're storing a JSON string (not a recipe object) in Vuex state
Look at your getRecipe action: you're running const recipe = JSON.stringify(response); before committing to state. That turns your recipe object into a plain string, so when you try to access properties like id later, you're not working with a valid object anymore. On top of that, you're not extracting the actual recipe data from the axios response—axios wraps API data in a data property!
Fix both actions in your Vuex module:
const actions = { initRecipes: ({commit}) => { axios.get('http://localhost:3000/recipes') .then((response) => { // Store the actual recipe array, not the full axios response object commit('RECIPES_LIST', response.data) }) .catch(err => { console.log(err); }); }, getRecipe: ({commit}, id) => { axios.get('http://localhost:3000/recipes/' + id) .then(response => { // Use response.data for the actual recipe data, no stringifying needed commit('GET_RECIPE', response.data); }) .catch(err => console.log(err)); }, // ... rest of your actions };
2. You're accessing the store getter before the API call finishes (async race condition)
In your getSingleRecipe method, you call this.getRecipe(this.id) (an async API call) and immediately assign this.recipe = this.$store.getters.singleRecipe. The API request hasn't completed yet, so you're grabbing the old state value—either the initial empty object or a previously fetched recipe.
Instead of storing recipe in component data, use a computed property that reacts to changes in Vuex state. This way, whenever the state updates after the API call, your component automatically gets the latest data.
3. Your Recipe List component is using recipes.data instead of just recipes
Since we fixed initRecipes to store response.data (the actual array of recipes), your list component no longer needs to access recipes.data—just loop over recipes directly.
Modified Code Snippets
Recipe List Component (template section)
<template> <div> <div class="col-md-6"> <!-- Loop directly over recipes, add a unique key for v-for --> <router-link :to="'/recipes/' + recipe.id" v-for="recipe in recipes" :key="recipe.id"> <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>
Recipe Details Component
<template> <div class="panel"> <div class="panel-heading"> <h1>{{singleRecipe.title}}</h1> </div> <div class="panel-body"> <p>{{singleRecipe.description}}</p> <p>Ingredients: </p> <ul> <li v-for="i in singleRecipe.ingredients" :key="i.id">{{i.ingredient}}</li> </ul> <router-link :to="{name: 'Update', params: {id: $route.params.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, mapGetters } from 'vuex'; export default { computed: { // Map the Vuex getter to a reactive computed property ...mapGetters(['singleRecipe']) }, watch: { '$route' (to) { // Fetch the new recipe when the route changes this.getSingleRecipe(to.params.id); } }, methods: { ...mapActions({ deleteTheRecipe: 'deleteRecipe', initRecipes: 'initRecipes', getRecipe: 'getRecipe' }), deleteRecipe() { this.deleteTheRecipe(this.$route.params.id); this.initRecipes(); this.$router.push('/recipes'); }, getSingleRecipe(id) { // Just trigger the API action—reactivity handles the rest this.getRecipe(id); } }, created() { this.getSingleRecipe(this.$route.params.id); } } </script>
Why this works:
- We're storing valid objects in Vuex instead of strings, so property access (like
id) behaves as expected. - The computed property
singleRecipeautomatically updates whenever the Vuex state changes, eliminating manual syncing of component data. - We fixed the async timing issue by letting Vue's reactivity system handle updates instead of trying to assign values before the API call finishes.
内容的提问来源于stack exchange,提问作者lejhbah

