Skip to content

Commit 871cb09

Browse files
Merge pull request #161 from preactjs/textarea-value-ssr
Fix SSR for <textarea value>
2 parents 81c3cdc + 47c4125 commit 871cb09

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

src/index.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
145145
}
146146

147147
// render JSX to HTML
148-
let s = '', html;
148+
let s = '', propChildren, html;
149149

150150
if (props) {
151151
let attrs = Object.keys(props);
@@ -156,7 +156,10 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
156156
for (let i=0; i<attrs.length; i++) {
157157
let name = attrs[i],
158158
v = props[name];
159-
if (name==='children') continue;
159+
if (name==='children') {
160+
propChildren = v;
161+
continue;
162+
}
160163

161164
if (name.match(/[\s\n\\/='"\0<>]/)) continue;
162165

@@ -194,6 +197,10 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
194197
if (name==='dangerouslySetInnerHTML') {
195198
html = v && v.__html;
196199
}
200+
else if (nodeName === 'textarea' && name === 'value') {
201+
// <textarea value="a&b"> --> <textarea>a&amp;b</textarea>
202+
propChildren = v;
203+
}
197204
else if ((v || v===0 || v==='') && typeof v!=='function') {
198205
if (v===true || v==='') {
199206
v = name;
@@ -241,7 +248,7 @@ function renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
241248
}
242249
s += html;
243250
}
244-
else if (props && getChildren(children = [], props.children).length) {
251+
else if (propChildren != null && getChildren(children = [], propChildren).length) {
245252
let hasLarge = pretty && ~s.indexOf('\n');
246253
let lastWasText = false;
247254

test/render.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,27 @@ describe('render', () => {
124124
expect(rendered).to.equal(expected);
125125
});
126126

127+
it('should serialize textarea value', () => {
128+
let rendered = render(<textarea value="abc" />),
129+
expected = `<textarea>abc</textarea>`;
130+
131+
expect(rendered).to.equal(expected);
132+
});
133+
134+
it('should escape textarea value', () => {
135+
let rendered = render(<textarea value={`a&b"c`} />),
136+
expected = `<textarea>a&amp;b&quot;c</textarea>`;
137+
138+
expect(rendered).to.equal(expected);
139+
});
140+
141+
it('should omit empty textarea value', () => {
142+
let rendered = render(<textarea value="" />),
143+
expected = `<textarea></textarea>`;
144+
145+
expect(rendered).to.equal(expected);
146+
});
147+
127148
it('should omit falsey children', () => {
128149
let rendered = render(<div>{null}|{undefined}|{false}</div>),
129150
expected = `<div>||</div>`;

0 commit comments

Comments
 (0)