Skip to content

Commit 11be5bf

Browse files
author
User
committed
Fix #270: Use value instead of defaultValue on <select> for Preact compat
Preact treats defaultValue as a plain HTML attribute and does not apply it to the DOM value property on <select> elements. Use value instead — Preact has special handling that applies value after <option> children have been reconciled, which correctly restores the selection on form re-render. Retain selected on <option> elements as a secondary cue so that even if Preact reconciles children in-place (updating rather than replacing), the <option> nodes carry the correct selection hint.
1 parent 5d4e674 commit 11be5bf

1 file changed

Lines changed: 10 additions & 5 deletions

File tree

src/reactpy_django/forms/transforms.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,22 @@ def convert_textarea_children_to_prop(vdom_tree: VdomDict) -> VdomDict:
3333

3434

3535
def set_value_prop_on_select_element(vdom_tree: VdomDict) -> VdomDict:
36-
"""Use the `value` prop on <select> instead of setting `selected` on <option>."""
37-
# If the current tag is <select>, remove 'selected' prop from any <option> children and
38-
# instead set the 'value' prop on the <select> tag.
36+
"""Set the `value` prop on <select> instead of relying on `selected` on <option>.
37+
38+
Preact applies ``value`` on ``<select>`` elements after child (``<option>``)
39+
reconciliation, which correctly restores the selection after a form re-render.
40+
``defaultValue`` is treated as a plain HTML attribute by Preact (unlike React
41+
which has special built-in handling for it), so ``defaultValue`` would NOT
42+
restore the selection on re-render — only ``value`` works reliably.
43+
"""
3944
if vdom_tree["tagName"] == "select" and "children" in vdom_tree:
4045
vdom_tree.setdefault("attributes", {})
4146
selected_options = _find_selected_options(vdom_tree)
4247
multiple_choice = vdom_tree["attributes"]["multiple"] = bool(vdom_tree["attributes"].get("multiple"))
4348
if selected_options and not multiple_choice:
44-
vdom_tree["attributes"]["defaultValue"] = selected_options[0]
49+
vdom_tree["attributes"]["value"] = selected_options[0]
4550
if selected_options and multiple_choice:
46-
vdom_tree["attributes"]["defaultValue"] = selected_options
51+
vdom_tree["attributes"]["value"] = selected_options
4752

4853
return vdom_tree
4954

0 commit comments

Comments
 (0)