2

Tree:

<Parent>
  <FnChild>
    <Target />
  </FnChild>
</Parent>

I have $validator provided by Parent. Inside FnChild I use render function with other async component (Target).

  inject: ['$validator'],
  render: (h, context) => {
    return h(Target, context.data, context.children)
  }

injections live inside context.injections, but how to pass it down to the Target by using functional component?

I can imagine only rewriting of FnChild as non-functional component and using provide: ['$validator'] in FnChild

UPD: as was pointed in answers, you don't need any inject/provide inside functional component, it just works.

My specific case was related to v-validate and auto-injection of new $validator in each component. And in my specific case it was a component with slot, which was overriding $validator because I had no inject: ['$validator'] inside it. Structure is a simple like this:

Parent

<ComponentWithSlot>
  <FnChild slot='my-slot' />
</ComponentWithSlot>

Parent had validator injected, but ComponentWithSlot hadn't, so new instance was recreated by v-validate for ComponentWithSlot and it was provided down to the FnChild instead of $validator from Parent component.

So once I've added inject: ['$validator'] into ComponentWithSlot, everything is fine and Target now correctly receives $validator from Parent.

Maksim Nesterenko
  • 5,661
  • 11
  • 57
  • 91
  • Why do you need to use a render-function in this scenario? I generally avoid using them unless absolutely necessary. – MJ_Wales Nov 12 '19 at 10:34
  • @MJ_Wales I think it's a good idea to use functional components when you don't really need instance or it is a component without any logic (in my case it's just resolver of another async component). So why not to do it more lightweight then? But in vue, it's usually painful to use functional component... because of weird way of working, bugs or weird api. – Maksim Nesterenko Nov 12 '19 at 12:28
  • Fair enough. I think the issue is a scoping issue. I'll post my thoughts – MJ_Wales Nov 12 '19 at 12:48
  • I'm unsure sorry, deleted my incorrect answer. – MJ_Wales Nov 13 '19 at 09:25

1 Answers1

2

provide/inject API is specifically designed to:

allow an ancestor component to serve as a dependency injector for all its descendants, regardless of how deep the component hierarchy is, as long as they are in the same parent chain.

  1. FnChild does't need to use inject: ['$validator'] at all
  2. No need to pass anything related to injections in FnChild render function
  3. Just use inject: ['$validator'] in your Target async component

Check this simple example

provide and inject are primarily provided for advanced plugin / component library use cases. It is NOT recommended to use them in generic application code.

tony19
  • 125,647
  • 18
  • 229
  • 307
Michal Levý
  • 33,064
  • 4
  • 68
  • 86