vdom manipulation, confusion ..
See original GitHub issuehttps://stackblitz.com/edit/js-o4semn Code and inspected result would tell the problem. But I’ll try to explain. I’m trying to achieve , a table component, which creates rows and cols automatically with given children like:
<MTable>
<th>x</th>
<th>Test</th>
<th>Test</th>
<input snr type="text" />
<input type="text" />
<input type="text" />
</MTable>
As you might see in the code in the link above, in render of the MTable I’m traversing children, if there isn’t a row ( tr ) or a “snr -> short for start new row” prop adding it, and continue. The thing that confuses me is , some extra -unwanted- rows in inputs ( you could see them with react dev tools or chrome dev tools ) appear , this breaks code in more complex scenarios .
I may made a mistake in render code - if so forgive me - but if code is correct there must be something wrong about vnodes.
For completeness I’m adding component code :
const T = (p) => {
const FieldTypes = ['input',];
let currentrow = null;
let thcurrentrow = null;
let thead = null;
let els = p.children.reduce(
(res, child) => {
let nodeName = getNodeName(child);
let ca = child.attributes || {};
if (FieldTypes.includes(nodeName)) {
if (!currentrow || ca.snr) {
currentrow = <tr ><td>{child}</td></tr>
res.push(currentrow);
}
else if (currentrow) {
currentrow.children.push(<td>{child}</td>);
}
return res;
}
else if (nodeName == "th") {
if (!thead) {
thead = <thead></thead>;
res.push(thead);
}
if (!thcurrentrow) {
thcurrentrow = <tr >{child}</tr>
thead.children.push(thcurrentrow);
}
else if (thcurrentrow) {
thcurrentrow.children.push(child);
}
return res; // added hope to fix, probably unnecessary ..
}
return res;
}, []);
return (
<table>{els}</table>
);
};
const getNodeName = c => c.nodeName ? (c.nodeName.name ? c.nodeName.name.toLowerCase() : c.nodeName.toLowerCase()) : "";
I’ve tried same -almost ( had to change some thing because of reacts dictation ) - code with react, and it worked. So I can conclude that the logic in render code is correct and this is a bug about vdom.
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (2 by maintainers)
Top GitHub Comments
@lewischa It’s the same api like for react: https://reactjs.org/docs/react-api.html#cloneelement
React is just ignoring children of
<input>
because the DOM doesn’t accept them.It seems like you’re inadvertently mutating VNodes in-place, which is going to produce unexpected results.
If you need to replace the children or props/attributes of an element (
child
), usecloneElement()
:It’s best to do so with a fully constructed array of children, rather than mutating the element’s children in-place.