Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS sever-side-rendering: computed property not seeing changes in store

I'm trying to get server side rendering to work in VueJS.

I've been following the official docs, and I'm attempting to get this example to work using axios. The endpoint is correct and the data does show up in the mutation.

https://ssr.vuejs.org/guide/data.html

I also found this page and tried most of these examples, which includes using getters, vuex mapState, mapGetter, etc:

vue.js 2 how to watch store values from vuex

Here is store/index.js:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

import { fetchPage } from './api'

export function createStore () {
    return new Vuex.Store({
        strict: true,

        state: () => ({
            res: {}
        }),

        actions: {
            actXY ({ commit }, page) {
                fetchPage('homepage').then((item) => {
                    commit('mutXY', { page, item });
                }).catch(error => {
                    throw new Error(`Store ${error}`);

                })
            }
        },

        mutations: {
            mutXY (state, { page, item }) {
                Vue.set(state.res, page, item);
                console.log(state.res.homepage.data)

            }
        },

        getters: {
            getXY (state) {
                return state.res
            }
        }
    })
}

the console log is displaying the correct information, so that means the axios endpoint is working and updating the state object. Originally, I was attempting to call the mutation, but I've since tried calling the getter. Unfortunately, the new data is not being updated in the getter, so of course, nothing new shows up in the component.

This is HomePage.vue:

<template>
  <div v-if="htmlData">{{ JSON.stringify(htmlData) }}</div>
  <div v-else>loading?</div>
</template>

<script>
export default ({
    name: 'homepage',

    computed: {
        htmlData () {
            console.log("computed = " + JSON.stringify(this.$store.state.res));
            console.log(this.$store.getters.getXY);
            return this.$store.getters
            // return this.getQuery()
        }
    },

    serverPrefetch () {
        return this.getData()
    },

    mounted () {
        console.log("in mounted")
        if (!this.item) {
            this.getData()
        }
    },

    methods: {
        getData () {
            return this.$store.dispatch('actXY', 'homepage')
        }
    }
})

</script>

As written, htmlData will show:

{"getXY":{}}

Yes, I did attempt many other variations on how to return the store item in the getter, but nothing is working.

Aside from the stuff in the above links, I've also looked around for variations on config files, I attempted to add async to store/actions, getData(), etc.

I also attempted to make the axios call directly in the component, which has had no success.

Since this is a project that was already more-or-less completed in VueJS that I'm converting to SSR, I removed everything from package.json and reinstalled every package, in the hopes that maybe one of the old vue packages was causing a conflict.

I also attempted the store code splitting from the official docs, and tried variations on how the routes are written. Nothing at all works.

I think I should add what the print statements show when I run my current code:

computed = undefined
computed mm  = undefined
getter = {}
computed get  = {"getXY":{}}
{
  title: 'Home'...}

The computed property in the component runs before the mutation is set. This causes the getter to be called before the mutation is updated. Likewise, if I'm attempting to call changes to res directly from the component, there is nothing in mutations when the store is being called and rendered.

This is a repo of the code I'm attempting to run: https://github.com/dt1/vue-ssr-attempt

(I figured out the answer. I've updated the repo with what is working for me, and explanation of my solution is below)

like image 1000
dizzystar Avatar asked May 16 '20 11:05

dizzystar


People also ask

Does Vue support server side rendering?

A server-rendered VueJS project can also be deemed isomorphic (rendering pages on both the server and client-side). In this article, I will guide you through the process of server-side rendering (SSR) with VueJS.

How do computed properties work in Vue?

In Vue. js, computed properties enable you to create a property that can be used to modify, manipulate, and display data within your components in a readable and efficient manner. You can use computed properties to calculate and display values based on a value or set of values in the data model.

Are computed properties reactive Vue?

The Basics of Vue Reactivity Simply put, a computed property's dependencies are the reactive values that help the property that determine the value that is returned. If none of these change, then, again, the cached value will be returned. If no reactive dependency is changed, a computed property is not recalculated.

Can you watch a computed property Vue?

Yes, you can setup watcher on computed property, see the fiddle.


1 Answers

First storeData() => storeData(state)

then return this.$store.state.items.homepage.data => return this.$store.state.items.homepage && return this.$store.state.items.homepage.data (or initialize the state items with an empty homepage)

like image 189
Renaud Avatar answered Nov 15 '22 05:11

Renaud