Closed edimitchel closed 4 years ago
This would be a very nice feature that deals with the verbosity of the return statement. It also makes it possible to truly group everything by logical concern when you have distinct features that aren't sharing state:
// currently
function setup() {
// Feature 1 (some stuff here)
const feature1Stuff = reactive({
...
})
// more feature 1 logic
// Feature 2
const feature2Stuff = reactive({
...
})
// more feature 2 logic
// But then part of feature 1 is down here too!
return { feature1Stuff, feature2Stuff }
}
// with this proposal
function* setup() {
// Feature 1
const feature1Stuff = reactive({
...
})
// more feature 1 logic
yield feature1Stuff
// Feature 2
const feature2Stuff = reactive({
...
})
// more feature 2 logic
yield feature2Stuff
}
In addition it will be really nice to get and expose values from a composition function in a single line, which is currently not possible.
yield ({ x: mouseX, y: mouseY } = useMousePosition())
Even if some people may not like this approach (they may prefer to have a return statement – one place where they can see everything that gets exposed to the template), it would be a useful alternative to have.
I feel like this would be better in a library.
Compare the RFC example:
// From RFC
const { id, setId } = useFeature()
yield { id, setId }
yield { name: ref('foo') }
// With:
const { id, setId } = useFeature()
return {
id, setId,
name: ref('foo')
}
// or even:
return { ...useFeature(), name: ref('foo') }
The yield version is not particularly shorter or clearer.
I would suggest: if your setup is large and made of independent features, split them into shorter functions and write a short setup that merge them instead of a long one with parts separated by yields:
// Factor out independent features
setup() {
return {
...feature1(),
...feature2(),
...feature3(),
}
}
// Instead of
*setup() {
// long feature 1
// ...
yield { ... }
// long feature 2
// ...
yield { ... }
}
If you prefer to use a generator you could easily do this with a library:
// Assume a defineYieldComponent function
// It simply replaces the setup on its argument with
// setup = (props, ctx) => mergeYields(originalSetup(props, ctx))
// mergeYields is left as an exercise to the reader ;)
export default defineYieldComponent({
*setup() {
const { id, setId = useFeature() }
yield { id, setId }
yield { name: ref('foo') }
}
})
This RFC would add a bit of complexity to core:
state = { ...toRefs(yield1), ...toRefs(yield2) }
? It's less efficient and what if I yield a markRaw
object (toRefs would warn)?Thanks for your answer @jods4 !
As I said, returning data with yield
goal is to get a more concise code. Your example was not relevant IMHO. Yes, in some way yield version is not shorter than traditional return. But I think returning value when we import create a nice and clean experience : about versioning, we don't change the return part, only the body of the setup function.
Also, as I mention, I adressed a proposal to TC39 for being able to extract directly a destructured object.
About typing, I check it and types are well infered : Yes, Vetur have to handle this specific case, but seriously, add each field I want to the TRC return is painful. Always do 2 actions for adding one feature is not a good experience.
Also, spreading directly a feature in the TRC is not a good practice, extracting field is more explicit.
Personally, this RFC should be added to the core because this adds a better experience and more concise code in general.
To be clear, I'm not arguing against the idea of using yield to build state.
I am just thinking it belongs more in a lib rather than inside core.
You can write defineYieldComponent
and use this today if you want to.
Your example was not relevant IMHO
Well, I copy-pasted the one from the RFC ;)
I adressed a proposal to TC39 for being able to extract directly a destructured object.
Don't hold your breath for JS changes. It usually takes years... that is, if it goes through. I personally don't think Vue should be designed with anything less than stage 3 in mind. If you want an example of something that's been desired for 6+ years by frameworks and has totally changed on the way and is still not stage 3, look no further than decorators.
About typing, I check it and types are well infered :
I have no doubt about setup
type being inferred properly.
It's the whole component + defineComponent
thing that worries me.
I definitely agree with you ;) I'll improve my RFC example ;)
Rendered
It's my first RFC. :)