When `render` directly returns `a custom object`, will throw an uncaught TypeError.
Vue version
3.3.4
Link to minimal reproduction
Steps to reproduce
click set to obj
button will throw warning:
Invalid VNode type:(undefined)
at <DemomodelValue=[object Object]onUpdate:modelValue=fn>
at <Repl>
and then click revert
button, will throw uncaught TypeError:
Uncaught (in promise): Cannot read properties of undefined (reading 'parentNode')
What is expected?
Whether it's warning against directly returning objects during development, catching that exception, or providing clearer warning instructions in the documentation, I would prefer it to be traceable rather than throwing an error in an unrelated place.
And, if possible, could the returned object be serialized? But I think this might bring more trouble, so maybe having a warning is sufficient.
By the way, about the documentation,
I have reviewed the documentation, and it mentions that you can also return strings or arrays
. However, it does not specify the consequences of returning an object.
What is actually happening?
I think that it is here where there is no strict validation whether child
is necessarily a VNode
.
https://github.com/vuejs/core/blob/37a14a5dae9999bbe684c6de400afc63658ffe90/packages/runtime-core/src/vnode.ts#L746-L750
I add a simple test in rendererComponent
:
test('render return object', async () => {
const root = nodeOps.createElement('div')
const App = {
render() {
return {info:'hi'};
}
}
render(h(App), root)
expect(serializeInner(root)).toBe(`[object Object]`)
})
child will be Object {info : "hi"}
, and then it will be cloned as a VNode
.
I think the starting point is here, causing a series of operations afterwards that lead to various kinds of exceptions being thrown.
System Info
No response
Any additional comments?
This is the process where my issue occurs:
When I was developing a component using TSX
, I wrote this piece of code:
<td class="m-td">{slot ? slot(...) : data}</td>
Due to the coding habit of SFC
, I didn't realize that using an object as data was incorrect. However, when I used the component, my data
(in the code) changed from a string to an object, and that's when the exception was thrown.
However, this exception completely prevents me from pinpointing the error, so I have to narrow down the scope gradually, which consumes some time.
And as you can see, in my various actions, it gives various warnings or errors, but it seems unrelated to the current behavior scenario.
So, I think it might be more user-friendly to add a conditional check and warning in
or directly check the __v_isVNode
property of the child
to route non-VNodes to the last else case
https://github.com/vuejs/core/blob/37a14a5dae9999bbe684c6de400afc63658ffe90/packages/runtime-core/src/vnode.ts#L750-L753
These approaches would provide a more friendly solution, relatively speaking.
If possible, I would be happy to submit a pull request to fix this issue.