I'm currently using Preact + Next.js with the configuration from nextjs-preact-demo. SSR with textareas seems to be breaking in Preact >=10.4.2.
CodeSandbox of last working version (10.4.1)
CodeSandbox of first broken version (10.4.2)
The textarea should be initialized with a value on page load.
The textarea is not initialized with a value on page load. The pre-rendered HTML seems to be the same between both 10.4.1 and 10.4.2, it just seems that Preact is not properly setting the textarea value during hydration.
I took some time to investigate this, and it looks like this issue has existed for a while, the only reason it worked in 10.4.1 is because preact-compat exported render in place of hydrate (fixed in #2511).
The quickest hack would be to make an exception for textarea nodes when props are diffed during hydration: https://github.com/preactjs/preact/blob/51836c926a0817aa8357df89aca08b48cb913a30/src/diff/index.js#L384-L385
However, this doesn't address the underlying issue that
<textarea value="foo"></textarea> instead of <textarea>foo</textarea><textarea>foo</textarea> if the value is set via the value prop rather than children.Just checked with the HTML spec and the value attribute is indeed not valid for <textarea> elements:
https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element
So the output of preact-render-to-string is correct.
React seems to automatically render the content of props.value as children for <textarea> and we should be able to do the same in preact/compat.
To fix this we should add the aliasing to `preact/compat麓. This can be done by adding the necessary lines somewhere around here, where other React-specific props handling is done:
Most helpful comment
Just checked with the HTML spec and the
valueattribute is indeed not valid for<textarea>elements:https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element
So the output of
preact-render-to-stringis correct.React seems to automatically render the content of
props.valueas children for<textarea>and we should be able to do the same inpreact/compat.To fix this we should add the aliasing to `preact/compat麓. This can be done by adding the necessary lines somewhere around here, where other React-specific props handling is done:
https://github.com/preactjs/preact/blob/5a1f9fbc32c2cb4ee5e946f6456d1579b53fb0c3/compat/src/render.js#L114-L131