do not require Props when using defineComponent with setup function
What problem does this feature solve?
I like that you can pass a setup function into defineComponent however if you require props in your component you then need to pass a component options object.
What does the proposed API look like?
I want to simply do this:
const MyComp = Vue.defineComponent((p: { name: string }) => {
return <div>{p.name}</div>;
});
instead of
const MyComp = Vue.defineComponent({
props: {
name: String
},
setup(p) {
return <div>{p.name}</div>;
}
});
This makes it look much cleaner and decreases a level of indentation.
This is even cleaner and works without explicitly setting props:
const MyComp = (p: { name: string }) => {
return <div>{p.name}</div>;
};
however it only works as a "Functional Component" and does not keep state. React lets me define components like this. In React I use Mobx to get Vue like Reactivity so I need to wrap my components in Observerable(). I would love to get the best of both worlds and have elegant jsx components with the proxy based Vue reactivity.
That's not supported right now, indeed. If no runtime props are declared, then ($)props
are empty - and everything you pass to that component will be in context.attrs
.
There has been some discussion about how we could make something like what you expect possible here:
https://github.com/vuejs/rfcs/discussions/282
But it has been going nowhere concrete yet.
I'll close this issue in favor of the RFC discussion.
What you can explore for your specific scenario though is:
const MyComp = Vue.defineComponent((p: { name: string }) => {
return <div>{p.name}</div>;
});
MyComp.props = ['name']
Ok, that is basically what I did by introducing this helper function:
function Component<T>(props: string[], setup: T): T {
let r = Vue.defineComponent(setup);
r.props = props;
return r;
}
@LinusBorg since all props are passed when you do not use defineComponent it seems like it should also work that way for consistency when using defineComponent.
I'm not sure what you mean when you say:
since all props are passed when you do not use defineComponent
I suspect you mix this up with functional components which are a different thing.
I'm not sure what you mean when you say:
since all props are passed when you do not use defineComponent
I suspect you mix this up with functional components which are a different thing.
Correct, that is what I meant (functional components). The only difference is one does not keep state, however they both allow for props to be passed but functional components do not require you to explicitly name them.
Stateful components do require that.
We can't change that behavior in 3.x for backwards compatibility. Most we can do is come up with a new option for enabling this on a per component Basis.
There has been some discussion about that In our RFC repo's discussions section, but it has dried up some time ago, there wasn't to much input coming.
I wonder if this could be enabled globally or have an alternative defineComponent that has that functionality. I personally think that setup functions should be stateful without wrapping them in a function and have functional components require the extra step. Since so many people are using typescript and jsx I think that making that feel very natural in Vue should be a goal.