[Bug] Can not get props from defineComponent function in tsx file
Vue version
3.2.45
Link to minimal reproduction
https://github.com/Lyon1994/vue-issues-project/tree/issues-001
Steps to reproduce
cd ${PROJECT_DIR}
pnpm i
pnpm dev
Open Browser, then you can find 'undefined' in web page
What is expected?
HelloWorld.tsx can get valid props from parent component.
Do not display 'undefined'
What is actually happening?
HelloWorld.tsx can not get valid props from parent component. It display 'undefined'
System Info
System:
OS: Linux 5.15 Deepin 20.7.1 20.7.1
CPU: (8) x64 Intel(R) Core(TM) i7-4720HQ CPU @ 2.60GHz
Memory: 3.74 GB / 15.52 GB
Container: Yes
Shell: 5.0.3 - /bin/bash
Binaries:
Node: 16.17.0 - /usr/local/bin/node
Yarn: 1.22.17 - ~/.local/bin/yarn
npm: 8.13.2 - ~/.local/bin/npm
Any additional comments?
HelloWorld
Component:
export interface HelloWorldProps {
msg: string;
}
export default defineComponent<HelloWorldProps>((props) => {
const msg = ref(props.msg);
if (!props.msg) {
console.error(
`Can not get props from defineComponent function in tsx file: props.msg=${props.msg}`
);
}
return () => (
<div>
<h1>
HelloWorld.tsx get props.msg {" => "}
<span style="color:red;">{props.msg ?? msg.value ?? "undefined"}</span>
</h1>
</div>
);
});
Vue component props can't be defined with types alone, they need to be defined at runtime as well.(*)
const component = defineComponent<HelloWorldProps>((props) => {
const msg = ref(props.msg);
if (!props.msg) {
console.error(
`Can not get props from defineComponent function in tsx file: props.msg=${props.msg}`
);
}
return () => (
<div>
<h1>
HelloWorld.tsx get props.msg {" => "}
<span style="color:red;">{props.msg ?? msg.value ?? "undefined"}</span>
</h1>
</div>
);
});
component.props = ['msg']
export default component
The above is roughly equivalent to the following, though that will likely break on a type level since the generic argument is being inferred from the props option:
export default defineComponent<HelloWorldProps>(
props: ['msg'],
setup: (props) => {
const msg = ref(props.msg);
if (!props.msg) {
console.error(
`Can not get props from defineComponent function in tsx file: props.msg=${props.msg}`
);
}
return () => (
<div>
<h1>
HelloWorld.tsx get props.msg {" => "}
<span style="color:red;">{props.msg ?? msg.value ?? "undefined"}</span>
</h1>
</div>
);
}
);
...or use a real functional component.
(*) Notes:
- in
<script setup>
, you can define props with types, but the compiler converts those to runtime definitions. - in functional components, you don't need props. but components wrapped in
defineComponent
are not functional components - even when you pass a function: that function would be used assetup()
in a normal component generated bydefineComponent
.
FYI: I have made a small unplugin to make the code work. https://github.com/so1ve/unplugin-vue-tsx-auto-props