0

I am retrieving posts from a Wordpress API and on scroll I want to load more posts and it works. But whenever I click on a post to open another route when I scroll on the bottom the app makes a call to the API, it basically runs the scroll() method from the other component. I am using the vue-router and axios.

Home Component:

    <template>
    <div class="container-fluid">
        <div class="container">
            <div class="row">
                <!--       Post         -->
                <div class="col-md-4 mb-4" v-for="post in posts" :key="post.id">
                    <div class="card h-100">
                        <div style="overflow: hidden">
                            <img class="card-img-top img-fluid" v-bind:src="post._embedded['wp:featuredmedia']['0'].source_url" alt="Card image cap">
                        </div>
                        <div class="card-body">
                            <router-link :to="{ path: '/article/' + post.slug, query: { id: post.id }, params: { title: post.slug }}">
                                <h5 class="card-title">{{ post.title.rendered }}</h5>
                            </router-link>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>

import axios from 'axios';

    export default {
        name: "Home",
        data(){
            return {
                posts: [],
                errors: [],
                pagination: 2,
                totalPages: null
            }
        },

        // Fetches posts when the component is created.

        methods: {
            getPosts() {
                axios.get('https://example.com/wp-json/wp/v2/posts?_embed')
                    .then(response => {
                        // JSON responses are automatically parsed.
                        this.posts = response.data;
                        this.totalPages = response.headers['x-wp-totalpages'];
                    })
                    .catch(e => {
                        this.errors.push(e)
                    });
            },

            scroll () {
                window.onscroll = () => {
                    let bottomOfWindow = document.documentElement.scrollTop + window.innerHeight === document.documentElement.offsetHeight;

                    if (bottomOfWindow) {
                        if(this.pagination <= this.totalPages) {
                            axios.get('https://example.com/wp-json/wp/v2/posts?_embed&&page=' + this.pagination)
                                .then(response => {
                                    this.posts = this.posts.concat(response.data);
                                    this.pagination = this.pagination + 1;
                                });
                        }
                    }
                };
            }
        },
        beforeMount() {
            this.getPosts();
        },

        mounted() {
            this.scroll();
        }

    }


</script>

<style scoped lang="scss">
    h1{
        font-weight: 300;
    }
    .card-body{
        a{
            color: #00b6f1;
            text-decoration: none;
            transition: 0.2s ease-in-out;

            &:hover{
                color: #62d4f9;
            }
        }
    }
</style>

Single post component:

<template>
    <div class="container-fluid">
        <div class="container">
            <div class="row">
                <div class="col-12 text-center mt-5 mb-5">
                    <img class="img-fluid" :src="featuredImage" alt="Card image cap">
                </div>
                <div class="col-12">
                    <h1>{{ title }}</h1>
                </div>
                <div class="col-12 content">
                    <p v-html="content">{{ content }}</p>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    import axios from "axios";


    export default {
        name: "Single",
        data(){
            return {
                post: {},
                featuredImage: null,
                errors: [],
                title: null,
                content: null,
            }
        },

        methods:{
            getPost() {
                axios.get('https://example.com/wp-json/wp/v2/posts/'+this.$route.query.id+'?_embed')
                    .then(response => {
                        // JSON responses are automatically parsed.
                        this.post = response.data;
                        this.featuredImage = response.data._embedded['wp:featuredmedia']['0'].source_url;
                        this.title = response.data.title.rendered;
                        this.content = response.data.content.rendered;
                    })
                    .catch(e => {
                        this.errors.push(e)
                    })
            },
        },
        beforeMount() {
            this.getPost();
        },
    }

</script>

<style lang="scss">
    .content{
        img, iframe{
            max-width: 100%;
            height: auto;
            margin: auto;
            display: block;
            margin-top: 30px;
            margin-bottom: 30px;
        }

        iframe{
            height: 300px;
        }

        p{
            color: #767676;
            font-size: 14px;
            line-height: 24px;
            font-weight: 400;
        }

        h2{
            color: black;
        }

        a {
            color: #00b6f1;
            text-decoration: none !important;
            transition: 0.2s ease-in-out;

            &:hover{
                color: #62d4f9;
            }
        }
    }
</style>
George2ps
  • 5
  • 4
  • I can’t see if that method is placed directly on the view or in an external component file. Maybe, you can just move it from the current position to another (outside the single post view file or in a component you don’t import there). Basically the `scroll()` method shouldn’t be present in the single post view. – Federico Moretti Mar 08 '20 at 08:13
  • Hello, the scroll method is inside the home view. When I go to the single post view where I don't use or mount the scroll method it still runs. Moreover, when I go directly to the single post view the scroll method doesn't run but when I go to the home view and back to the single post view the scroll methods runs again everywhere – George2ps Mar 08 '20 at 08:20
  • I added better screenshots from both components – George2ps Mar 08 '20 at 08:26
  • See https://stackoverflow.com/help/how-to-ask , The question should contain the code, not images. – Estus Flask Mar 08 '20 at 08:33

1 Answers1

0

Try this in Home.vue:

beforeDestroy() {
  this.scroll = null
  delete this.scroll
}

It happens because, when changing route, the scroll() method is still mounted. This should prevent it from being loaded elsewhere than in Home.vue.

Federico Moretti
  • 527
  • 1
  • 11
  • 22
  • Thanks, the hook works but the the function inside doesn't. It still runs on other views. Is there a way to unmount the function? – George2ps Mar 08 '20 at 09:39
  • I believe there is something to do with the `window.onscroll` function. I tried the `scroll()` function with `console.log` and it deleted the function successfully when I changed route. – George2ps Mar 08 '20 at 09:54
  • Try with my update. It should work, but if it doesn’t, try calling `destroyed` instead of `beforeDestroy`. More on Vue.js lifecycle: https://scotch.io/tutorials/demystifying-vue-lifecycle-methods – Federico Moretti Mar 08 '20 at 10:13
  • 2
    tried it, didn't work. But I figured out a different way, like this: `destroyed() { window.onscroll = null; }` and works. I'm not sure if this is right but works, thank again – George2ps Mar 08 '20 at 10:25
  • Maybe it treats `scroll` as a reserved word for `windows.scroll`, as you imagined. – Federico Moretti Mar 08 '20 at 10:33
  • 1
    It's because you have bound an anonymous function to the global `window.scroll` event. As you're using a single page app, it is still bound even if the component is not in scope anymore because the page is not refreshed. To remove it, you indeed need to set `window.scroll` to null. Deleting `this.scroll` has no effect because it is not bound to window.scroll, but the anonymous function still is. – thibautg Mar 08 '20 at 17:38