Search code examples
vue.jsvue-componentvuexnuxt.js

v-on:click never firing on button in Nuxt component, because of middleware


I've seen this elsewhere in other questions, but haven't seen a solution. I'm trying to make a simple GDPR cookie notification that closes on click, using a button. I'm in Universal mode, meaning mounted() isn't available, so I'm trying to set cookies through Vuex. However, the click event I have bound to the button in my component isn't firing.

Edit: After building a codesandbox version of my app, which worked as it should, I went through and hacked up my Nuxt app until I found what was causing the problem. As it turns out, it was my middleware, and more specifically, the fact that I was using the fs-extra library to read JSON files. Still not clear on why this is happening, so any suggestions are welcome. The code below includes my middleware.

components/CookieNotice.vue

<template>
    <div v-if="cookie != true" class="cookie_notice_wrap">
        <div class="cookie_notice">
            <p class="notice_message">This site uses cookies for analytics purposes.</p>
            <button @click.prevent="dismissNotification" class="notice_dismiss">Close</button>
    </div></div>
</template>

<script>
import { mapGetters } from "vuex";

export default {
    name: "CookieNotice",
    methods: {
        dismissNotification: function(e) {
            console.log("we clicked?");
            document.querySelector(".cookie_notice_wrap").classList.add("hidden_click");
            this.store.dispatch("cookieStateChange", true);
        }
    },
    computed: {
        ...mapGetters(["cookie"]),
    }
}

</script>

Actions from store/index.js

export const actions = {
    async getPosts({ state, commit, dispatch }) {
        if (state.posts.length) {
            return
        }

        try {
            await axios.get("/api/json-access");
        }
        catch (err) {
            console.log(err);
        }
    },
    nuxtServerInit({ state, commit, dispatch }, { req }) {
        dispatch("getPosts");

        const seen = this.$cookies.get("cookie_notice_seen");
        if (!seen) {
            dispatch("cookieStateChange", false);
        }
    },
    cookieStateChange({state, commit, dispatch}, bool) {
        // this does set the cookie correctly, unsure if it will work the same when bound to the button click
        commit("updateCookie", bool);
        this.$cookies.set("cookie_notice_seen", bool, {
            path: "/",
            maxAge: 60 * 60 * 24 * 7
        });
    }
}

~/middleware/api/json-access.js:

const fse = require('fs-extra');
import axios from 'axios';

const storeLocation = "middleware/full_site.json";

export default async function({ store, route, redirect }) {
    const exists = await fse.pathExists(storeLocation);
    let posts;

    if (!exists) {
        await fse.ensureFile(storeLocation);
        posts = await postsFromWP();
        fse.writeJSON(storeLocation, posts);
    }
    else {
        try {
            posts = await fse.readJSON(storeLocation);
        }
        catch (err) {
            console.log(err);
        }
    }

    store.commit("updatePosts", posts);
}

async function postsFromWP() {
    const url = ".../example/json/file.json";
    const config = { headers: { "Accept": "application/json" }};
    let posts = await axios.get(url, config);

    posts = posts.data
        .filter(el => el.status === "publish")
        .map(({ id, slug, title, excerpt, date, tags, content }) => ({
            id, slug, title, excerpt, date, tags, content
        }));

    return posts;
}

I had the middleware configured in nuxt.config.js via routes -> middleware before, but currently have it set to go through serverMiddleware instead, for testing. I also added the action that triggers getting the posts, in case that's also part of it. This has definitely hit on a limit of my Nuxt/Vue understanding - I have no idea why this could be happening, so any wisdom is much appreciated.


Solution

  • If you wind up dealing with something similar, fs or fs-extra are your culprits. You can't use file operations on the client side, which is when these middleware actions are happening (I think). The cookie notice only fully worked when I removed the fs-extra import at the very top of the middleware file.