Vue-next: Setup context hook for dependency injection

Created on 16 Jul 2020  路  7Comments  路  Source: vuejs/vue-next

What problem does this feature solve?

Here is a utility helper I like to use

export function useLocalModel ({ props, emit }, propName) {
  return computed({
    get () {
      return props[propName];
    },
    set (val) {
      emit(`update:${propName}`, val);
    },
  });
}

Here, the dependency injection is cumbersome / no conventions + no standard (should the argument be the first one ? the last one ?)

What does the proposed API look like?

Thinking about it, I came up with an elegant solution, that I don't think would be super difficult to implement:
Introduce a new built-in useContext composition function that would allow users to get the current setup function context (props, attrs, emit, slots).
Here it will make this composition a lot more clean and simple:

import { useContext } from 'vue'
export function useLocalModel (propName) {
  const { props, emit } = useContext()
  return computed({
    get () {
      return props[propName];
    },
    set (val) {
      emit(`update:${propName}`, val);
    },
  });
}

This is probably too simple to raise a RFCs but if there is a need, feel free to ask.
Regards.

enhancement

Most helpful comment

getCurrentInstance is advanced api and you should be really careful using it, in this case I believe is fair to use it.

There's my implementation of the vmodel composable https://github.com/pikax/vue-composable/blob/master/packages/vue-composable/src/misc/vmodel.ts

All 7 comments

Could you use the existing getCurrentInstance function for what you are trying to do?

import { getCurrentInstance } from "vue"
export function useContext() {
  const { props, emit, slots, attrs } = getCurrentInstance()
  return { props, emit, slots, attrs } // assuming you aren't interested in the whole vm
}

The main caveat here I think is that the props, slots, and attrs in setup have an additional proxy wrapper around each of them, and when using getCurrentInstance you have unproxied slots and attrs (and one less proxy around props). Not sure if that might introduce some inconsistencies.

@aztalbot I was not aware of this API, sounds like it's exactly what I'm looking for! thanks.
I leave it open because of

The main caveat here I think is that the props, slots, and attrs in setup have an additional proxy wrapper around each of them, and when using getCurrentInstance you have unproxied slots and attrs (and one less proxy around props). Not sure if that might introduce some inconsistencies.

well, in my mind composition API scope is much bigger than just dealing with reusable state & lifecycle. To me it was brought in to overcome shared component logic issues with mixins as a whole.

You can have the same thing in options API without the need for extra hooks just by using a factory function:

export const createPropModel = (propName) => ({
  get () { return this[propName] },
  set (value) { this.$emit(`update:${propName}`, value) }
})

@CyberAP I don't really get your point..
The goal is to use the composition API here.

Composition API is not an ideal candidate for this task it seems to me. getCurrentInstance is an advanced API for plugins and I think it's not a best suit to automate computed model creation. Instead I'd suggest to take a look at this RFC which aims to simplify the exact same task, but in a declarative manner.

getCurrentInstance is advanced api and you should be really careful using it, in this case I believe is fair to use it.

There's my implementation of the vmodel composable https://github.com/pikax/vue-composable/blob/master/packages/vue-composable/src/misc/vmodel.ts

Was this page helpful?
0 / 5 - 0 ratings