From b99c91c149881139cf2a7f39f43375f69a646664 Mon Sep 17 00:00:00 2001 From: Andre Wiggins <459878+andrewiggins@users.noreply.github.com> Date: Tue, 14 Feb 2023 10:50:05 -0800 Subject: [PATCH] Fix hydrating textarea with value prop (#3891) * Fix hydrating textarea with value prop * Golf setting value --- compat/src/render.js | 19 +++++++++++++++++++ compat/test/browser/textarea.test.js | 18 +++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/compat/src/render.js b/compat/src/render.js index 5e923667fd..2e54fcba85 100644 --- a/compat/src/render.js +++ b/compat/src/render.js @@ -223,6 +223,25 @@ options._render = function(vnode) { currentComponent = vnode._component; }; +const oldDiffed = options.diffed; +/** @type {(vnode: import('./internal').VNode)} */ +options.diffed = function(vnode) { + if (oldDiffed) { + oldDiffed(vnode); + } + + const props = vnode.props; + const dom = vnode._dom; + if ( + dom != null && + vnode.type === 'textarea' && + 'value' in props && + props.value !== dom.value + ) { + dom.value = props.value == null ? '' : props.value; + } +}; + // This is a very very private internal function for React it // is used to sort-of do runtime dependency injection. So far // only `react-relay` makes use of it. It uses it to read the diff --git a/compat/test/browser/textarea.test.js b/compat/test/browser/textarea.test.js index d1c114ec7d..9162a440a3 100644 --- a/compat/test/browser/textarea.test.js +++ b/compat/test/browser/textarea.test.js @@ -1,8 +1,10 @@ -import React, { render, useState } from 'preact/compat'; +import React, { render, hydrate, useState } from 'preact/compat'; +import ReactDOMServer from 'preact/compat/server'; import { setupScratch, teardown } from '../../../test/_util/helpers'; import { act } from 'preact/test-utils'; describe('Textarea', () => { + /** @type {HTMLElement} */ let scratch; beforeEach(() => { @@ -19,6 +21,20 @@ describe('Textarea', () => { expect(scratch.firstElementChild.value).to.equal('foo'); }); + it('should hydrate textarea value', () => { + function App() { + return '); + + hydrate(, scratch); + expect(scratch.firstElementChild.value).to.equal('foo'); + expect(scratch.innerHTML).to.be.equal(''); + }); + it('should alias defaultValue to children', () => { // TODO: IE11 doesn't update `node.value` when // `node.defaultValue` is set.