`Inject()` 3rd argument default value is not `true`
Vue version
latest
Link to minimal reproduction
Steps to reproduce
API: Composition - Inject()
Issue: Inject()
3rd argument default value is not true
.
However, the API Docs type
description says true
.
It is implemented with very simple code. Just open the playground and check the console log in developer tools.
What is expected?
Inject()
expects third argument default value is true
.
What is actually happening?
Inject()
expects third argument default value is false
.
System Info
It was run with the latest version on the playground. This is an issue independent of the runtime environment.
Any additional comments?
During the production of the Vue3 Korean document, I found it during the verification stage of the example code.
This can be confusing for many novice developers.
First, I submitted an issue to vuejs/docs and was told to resubmit here.
I think so too. So I opened an issue in vuejs/docs. However, the member told me to report the issue here as it is not a document issue.
I just hope this problem gets resolved quickly.
@edison1105 we also have this export:
export function inject<T>(
key: InjectionKey<T> | string,
defaultValue: T | (() => T),
treatDefaultAsFactory: true
): T
Are we sure we always want to treat the third argument as false
? I am happy to modify docs but from the user experience position it would be better if we eagerly treated default value as a factory, unless we explicitly disable this behaviour.
@edison1105 we also have this export:
export function inject<T>( key: InjectionKey<T> | string, defaultValue: T | (() => T), treatDefaultAsFactory: true ): T
Are we sure we always want to treat the third argument as
false
? I am happy to modify docs but from the user experience position it would be better if we eagerly treated default value as a factory, unless we explicitly disable this behaviour.
Thanks for your reply. I see that override of inject. But that's for typescript usage, actually the third args is always false. /cc @LinusBorg what do you think?🤔
Apart from the question of what Evan's intended behavior was, the main question is: What's the more common usage?
My gut tells me that it's more common to provide a function (and thus need a function as a default was well), than it is to require a factory function for creating the default value.
Mainly because inject()
is usually only called only once per component anyway, and in that moment we can create a per-component default just fine without a factors function:
setup () {
const myInjectedMap = inject('myKey', new Map()) // no factory function needed.
}
Unless I overlooked an obvious use case for factory functions, I'd say they are a real edge case, and the default value for the third argument should therefore be false.
@LinusBorg I've seen cases when people use a factory function returning an array or object for a default value, just like they do it for the default prop value. I am not sure whether they need it to be a factory function but it aligns logically with props default so I can see where this comes from.
@yyx990803 it would be nice to have your input on the treatDefaultAsFactory
inject
argument so we could align documentation to the source code or vice versa 😅
edison1105 we also have this export:
export function inject<T>( key: InjectionKey<T> | string, defaultValue: T | (() => T), treatDefaultAsFactory: true ): T
see
Are we sure we always want to treat the third argument as
false
? I am happy to modify docs but from the user experience position it would be better if we eagerly treated default value as a factory, unless we explicitly disable this behaviour.
My two cents, I think this export means that, the 3rd argument treatDefaultAsFactory
should always be explicitly passed with true
when the 2nd argument is a function, acts like there is no default value for the 3rd argument.
"true" here is a literal type which means it should be true and true only, not that you can omit this argument (otherwise it should be written like "treatDefaultAsFactory = true")
So I suggest the second last example in the docs should be changed from
const baz = inject('foo', () => new Map())
to
const baz = inject('foo', () => new Map(), true)
My original line of thought was similar to what @LinusBorg wrote: sing a default value when injecting is relatively uncommon, using a factory function is indeed rare. This is only needed when the user explicitly need a way to avoid unnecessary initialization cost.
Some other aspects:
- It can be confusing if functions get special treatment by default. It makes more sense to opt-in to the special case.
- The current behavior has existed for a long time, and adjusting it would be a breaking change.
I have updated the docs via https://github.com/vuejs/docs/commit/79b448d5fc71a910c3ab60ddecc5c55458eb4526 and https://github.com/vuejs/docs/pull/2317.