Vue component not showing updated Vuex data

Viewed 52

I realise this is a common issue with people new to vue and vuex, but I've been using it for two years now and thought I understood the ins and outs. Yet I'm stumped. There must be something I'm overlooking.

We've got a couple of complex models that used to have layouts hard-coded in the front end, and now some of those come from the backend instead, so I added a store module to handle that:

import { ActionTree } from 'vuex';
import { RootState } from '@/store';
import request from '../../services/request';
import layouts from '../../layouts';

export const types = {
  FETCH_LAYOUT: `${MODULE_NAME}${FETCH_LAYOUT}`,
};

const initialState = {
  layout: layouts,
};

const actions: ActionTree<LayoutState, RootState> = {
  async [FETCH_LAYOUT]({ commit, state }, id) {
    if (!state[id]) {
      const layout = await request.get(`layout/${id}`);
      commit(types.FETCH_LAYOUT, { layout, id });
    }
  },
};

const mutations = {
  [types.FETCH_LAYOUT](state: any, { layout, id }) {
    state.layout[id] = layout;
  },
};

export default {
  namespaced: true,
  state: initialState,
  getters: {},
  actions,
  mutations,
};

Everything here seems to work fine: the request goes out, response comes back, state is updated. I've verified that that works. I've got two components using this, one of them the parent of the other (and there's a lot of instances of the child). They're far to big to copy them here, but the import part is simply this:

computed: {
  ...mapState({
    layout: (state: any) => {
      console.log('mapState: ', state.layout, state.layout.layout[state.modelName]);
      return state.layout.layout[state.modelName];
    },
  }),
},

This console.log doesn't trigger. Or actually it looks like it does trigger in the parent, but not in the children. If I change anything in the front-end code and it automatically loads those changes, the child components do have the correct layout, which makes sense because it's already in the store when the components are rerendered. But doing a reload of the page, they lose it again, because the components render before the layout returns, and they somehow don't update.

I'm baffled why this doesn't work, especially since it does seem to work in the parent. Both use mapState in the same way. Both instantiate the component with Vue.component(name, definition). I suppose I could pass the layout down as a parameter, but I'd rather not because it's global data, and I want to understand how this can fail. I've considered if maybe the state.layout[id] = layout might not trigger an automatic update, but it looks like it should, and the parent component does receive the update. I originally had state[id] = layout, which also didn't work.

Using Vue 2.6.11 and Vuex 3.3.0

0 Answers
Related