Consider the following markup:
<div id="app"><div class="app"><ul><li>1</li></ul></div></div>
and the following code:
function App() {
return <div className="app"><List/></div>
}
function List() {
return <ul suppressHydrationWarning={true}><Item key="1" name="1"/><Item key="2" name="2"/></ul>
}
function Item({name}) {
return <li name={name}>{name}</li>
}
hydrate(<App/>, document.querySelector('#app'));
Note, that the initial markup is missing <li name="2">2</li>.
The result is:
<div class="app"><ul><li>1</li><li>2</li></ul></div>
Notice that the name="2" attribute is missing.
React sets attributes on the filled-in elements. I think this should be the expected behavior.
Attributes are missing for filled-in elements (the name="2" attribute is missing).
This is the expected behavior. In Preact hydrate() is an optimized fast-path that skips nearly all of the diffing logic. It is only meant to attach event listeners. This is the quickest way to boot up an SPA. If you want the initial render to replace/patch attributes and or full DOM nodes render() is the way to go 馃憤
Hmm - we don't set attributes on hydrated elements, but we should be setting attributes on any newly constructed DOM subtrees. I thought this was something we fixed in one of the 10.4.x releases? We flip the hydrate bit here and that seems like it should be triggering attribute diffing.
Looks you might just need to update your Preact version @dvoytenko - the current version works as you described:
https://jsfiddle.net/developit/tdfxpv3g/

@developit @marvinhagemeister So it is. Just retried on 10.4.8 and it's fixed. Definitely no argument that existing elements should be left along. This only matters for newly constructed ones. Thanks for the quick turnaround!
Most helpful comment
Looks you might just need to update your Preact version @dvoytenko - the current version works as you described:
https://jsfiddle.net/developit/tdfxpv3g/