Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass state property via props (Vuex)

I have a component that should display data from the store, but the component is reusable, so I would like to pass the name of the store module and property name via props, like so:

<thingy module="module1" section="person">

Then, in the component:

<template>
  <h2>{{ title }}</h2>
  <p>{{ message }}</p>
</template>

<script>
import { mapState } from 'vuex';
import get from 'lodash.get';

export default {
  props: [
    'module',
    'section',
  ],
  computed: mapState(this.module, {
    title: state => get(state, `${this.section}.title`),
    message: state => get(state, `${this.section}.message`),
  })
}
</script>

The problem is, it seems the props are undefined at the time when mapState() is executed. If I hardcode the prop values, the component works. Also, if I log the props in the created() hook, I get the expected values. So it seems like a race condition.

Am I going about this the wrong way here?

Update

The module namespace must be passed from within the mapping function, like so:

computed: mapState({
  title() {
    return get(this.$store.state, `${this.module}.${this.section}.title`);
  },
  message() {
    return get(this.$store.state, `${this.module}.${this.section}.message`);
  }
})

(note that get() is a lodash, not a vue function)

This can be further abstracted into a mixin.

like image 930
Christof Avatar asked Mar 24 '17 13:03

Christof


1 Answers

Note the comment in the mapState example:

// to access local state with `this`, a normal function must be used
countPlusLocalState (state) {
  return state.count + this.localCount
}

You are using arrow functions.

As for this.module, I think you're going to have to forego the binding helper notation and explicitly put the module reference into the definitions. I'm guessing that looks like:

computed: mapState(this.module, {
  title(state) {
    return get(`${state}.${this.module}`, `${this.section}.title`);
  },
  message(state) {
    return get(`${state}.${this.module}`, `${this.section}.message`);
  }
})
like image 59
Roy J Avatar answered Oct 13 '22 13:10

Roy J