Home > Enterprise >  how can i update reviews in same routes without refreshing the page in vuejs
how can i update reviews in same routes without refreshing the page in vuejs

Time:09-28

i have a blog app which i'm trying to add reviews , but i have to hard refresh before updating the reviews on my my blog route

this is my blog id route

<template>
  <div>  
      <h3 > {{blog.title}}</h3>
      <p >
        {{blog.description}}
      </p>
  <Review />
  <reviewSection/>
  </div>
</template>

<script>
import axios from "axios";
import Review from "../components/Review.vue";
import reviewSection from "../components/reviewSection.vue";
export default {
  components: {
  },
  data() {
    return {
      blog: []
    };
  },
  watch: {},
  created() {
 axios
      .get(`http://localhost:4000/api/blogs/${this.$route.params.id}`, {})
      .then(response => {
        this.blog = response.data.blog;
      })
      .catch(error => {
        console.log(error);
      });
  },

};
</script>

this is how i addd reviews which i'm importing as a component in blog id

<template>
              <div >
                <textarea
                  placeholder="Add a comment"
                  v-model="body"
                ></textarea>
              </div>
            <div >
              <button
                
                @click="onAddReview"
              >Submit</button>
            </div>
</template>

<script>
import axios from "axios";
export default {
  data() {
    return {
      body: "",
    };
  },
  methods: {
    async onAddReview() {
      try {
        var data = {
          body: this.body,
        };
        let response = await axios.post(
          `http://localhost:4000/api/reviews/${this.$route.params.id}`,
          data,
        );   
      } catch (err) {
        console.log(err);
      }
    }
  }
};
</script>

this is my review section which i display the reviews on the same blog id page

<template>
  <div>
    <div
      v-for="review in reviews"
      :key="review._id"
      
    >
      <div >     
          <div >
            {{ review.body }}
          </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";
export default {
  data(){
 return {
      reviews: null,
    };
  },
 watch: {
    "$route.params.id": {
      handler(newVal) {
        this.loadReviews(newVal);
      }
    }
  },
 methods: {
    loadReviews(id) {
      axios
        .get(`http://localhost:4000/api/reviews/${id}`, {})
        .then(response => {
         // console.log(response);
          this.reviews = response.data.reviews;
        })
        .catch(error => {
          console.log(error);
          error;
        });
    },
  }
};
</script>

how can i update the review without hard refreshing my blog id page

CodePudding user response:

The convention in Vue or libraries like it in general (e.g React) is you emit an event and pass down props.

You emit an event when something happens in general. In your example, an event you are interested in would be something like submitted on your "CreateReview" component.

(A good tip in general is thinking about what your component should emit right away. If there's too many or seems like something is not relevant, that's a sign you have another component inside that can be extracted.)

Now that you know you can handle an event, it's just a matter of how to react to it (thus it's called a reactive framework).

There's a lot of ways you can do this:

  • With the concept of Smart and Dumb/Presentational components:
<!-- This is your page/App.vue -->
<template>
  <div>
    <ReviewForm @submitted="onSubmit" />
    <ReviewList :reviews="reviews" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      reviews: []
    }
  },

  mounted() {
    this.fetchReviews()
  },

  methods: {
    fetchReviews() {
      // ....
    },

    // The subjective part.
    onSubmit(review) {
      // Just append the new data and save 1 API call
      this.reviews.push(review)

      // Fetch from API again if you have complex sorting.
      // You might not need to pass the `review` in the event.
      this.fetchReviews()
    }
  }
}
</script>

With this, you have:

  • a Smart component (could be your page.vue or a dedicated smart component) that handles the logic
  • a Dumb/Presentational component that just renders what's given to it

  • Imperative way
<template>
  <div>
    <ReviewForm @submitted="onSubmit" />
    <ReviewList ref="list" />
  </div>
</template>

<script>
  methods: {
    onSubmit() {
      this.$refs.list.fetchReviews()
    }
  }
</script>

If you don't want Smart/Dumb components and just want components that encapsulate things then you can do this.

Just be wary that this might turn into habit. Vue's standard way of doing things should be reactive which means reacting to events.

You can avoid the imperative thing and make it reactive by using Vuex/Pinia and have your components directly interact with data without the help of a parent component but that might be overkill for this situation.

  • Related