Search code examples
javascriptapivue.jssession-storage

Vue adding to existing session storage array


I've built an API that sends a video with all of its comments and in the front end, the video is called on mount. I have a create comment button that calls a createComment route that adds a comment to the video and saves it in the database. However, the new comment does not appear because after the first get all videos fetch is called, the code then uses session storage to keep the videos and not have to call to the API on every mount. Is there any way I could add the new comment to the session storage. All comments are stored within their video so video is an object with a comments array property.

Thank you for any help with this.

HOME PAGE

<template>
    <div class="home">
        <SelectedVideo v-bind:user="user" v-bind:video="videos[0]"/>
    </div>
</template>

<script>
    import axios from 'axios';
    import SelectedVideo from '../components/SelectedVideo.component';
    axios.defaults.withCredentials = true;

    export default {
        name: 'Home',
        components: {
            SelectedVideo
        },
        data() {
            return {
                videos: [],
                user: null
            }
        },
        created() {
            if (sessionStorage.homeVideos) {
                console.log('Getting from session storage...');
                this.videos = JSON.parse(sessionStorage.homeVideos);
            } else {
                console.log('Getting from API and setting res to session storage...');
                axios.get('http://localhost:8000/api/v1/videos')
                .then(res => {
                    sessionStorage.setItem('homeVideos', JSON.stringify(res.data.data.videos));
                    this.videos = JSON.parse(sessionStorage.homeVideos);
                })
                .catch(err => console.log("ERROR: " + err.response.data.message));
            }
        },
        mounted(){
            if (sessionStorage.user) {
            // this.videoId = video._id
            this.user = JSON.parse(sessionStorage.user);
            }
        }
    }
</script>

<style lang="scss" scoped>

</style>

Selected Video component

<template>
    <div class="selected">
        <h2 class="selected__title">{{video.title}}</h2>
        <video class="selected__video" :src=video.video controls :poster=video.thumb></video>

        <div style="width: 70%;">
            <div class="selected__details">
                <h3 class="selected__details__views">300 views</h3>

                <div class="selected__thumbs">
                    <div class="selected__like">&#128077; 47</div>
                    <div class="selected__dislike">&#128078; 3</div>
                </div>
            </div>

            <form class="selected__commentbox">
                <label for="comments" class="selected__commentbox__label">Comments</label>
                <textarea v-model="text" class="selected__commentbox__textarea" rows="4" id="comments" placeholder="Type a sweet comment..."></textarea>

                <button @click="handleSubmit" class="selected__commentBtn">add comment</button>
            </form>


            <div v-bind:key="comment._id" v-for="comment in video.comments" class="selected__comments">
                <Comment v-bind:comment="comment"/>
            </div>
        </div>
    </div>
</template>

<script>
    import Comment from './Comment.component.vue';
    import axios from 'axios';

    export default {
        name: 'SelectedVideo',
        data() {
            return {
                text: null,
                videoId: this.video._id,
                userId: this.user._id
            }
        },
        props: ["video", "user"],
        components: {
            Comment
        },
        methods: {
            handleSubmit(event) {
                event.preventDefault();
                this.createComment(this.text, this.videoId, this.userId);
                this.text = '';
            },
            async createComment(comment, video, user) {
                try{
                    const res = await axios({
                        method: 'POST',
                        url: 'http://localhost:8000/api/v1/comments/',
                        data: {
                            comment,
                            video,
                            user
                        }
                    });
                    if (res.data.status === 'success') {
                        // location.reload(true);
                        console.log(res);
                    }
                } catch(err) {
                    console.log(err.response.data.message);
                }
            }
        }
    }
</script>

Solution

  • To achieve what you described, I think there some changes need to made in your files beside sessionStorage logic to make it work. First, you need to add a method so that the SelectedVideo.vue can update the video comments in its parent, which is Homepage

    Homepage

    <SelectedVideo v-bind:user="user" v-bind:video="videos[0]" @updateComment=updateComment/>
    
    methods: {
     updateComment(comments) {
      this.$set(this.videos, 0, {...this.videos[0],...comments}); //update Vue video list
      sessionStorage.setItem("homeVideos", JSON.stringify(this.videos)); // update sessionStorage for future load
     }
    }
    

    Second, after getting the new comments, you need to call the parents updateComment methods so that it can update the videos list

    SelectedVideo.vue

    async createComment(comment, video, user) {
                try{
                    const res = await axios({
                        method: 'POST',
                        url: 'http://localhost:8000/api/v1/comments/',
                        data: {
                            comment,
                            video,
                            user
                        }
                    });
                    if (res.data.status === 'success') {
                        this.$emit("updateComment", res.data.data); // call parents update method
                        console.log(res);
                    }
                } catch(err) {
                    console.log(err.response.data.message);
                }
            }