-
-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Description
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
.
core/packages/runtime-core/src/vnode.ts
Lines 746 to 750 in 37a14a5
} else if (typeof child === 'object') { | |
// already vnode, this should be the most common since compiled templates | |
// always produce all-vnode children arrays | |
return cloneIfMounted(child) | |
} else { |
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
core/packages/runtime-core/src/vnode.ts
Lines 746 to 750 in 37a14a5
} else if (typeof child === 'object') { | |
// already vnode, this should be the most common since compiled templates | |
// always produce all-vnode children arrays | |
return cloneIfMounted(child) | |
} else { |
or directly check the __v_isVNode
property of the child
to route non-VNodes to the last else case
core/packages/runtime-core/src/vnode.ts
Lines 750 to 753 in 37a14a5
} else { | |
// strings and numbers | |
return createVNode(Text, null, String(child)) | |
} |
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.