Skip to content

Commit 72f6081

Browse files
committed
actually fix #684
Because we handle events asynchronously, we must leave the value uncontrolled in order to allow all changed committed by the user to be recorded in the order they occur. If we don't, the user may commit multiple changes before we render resulting in prior changes being overwritten by subsequent ones. Instead of controlling the value, we set it in an effect. This feels a bit hacky, but I can't think of a better way to work around this problem.
1 parent c9536f6 commit 72f6081

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

docs/source/_custom_js/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/client/packages/idom-client-react/src/components.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ export function Element({ model }) {
3838
}
3939
} else if (model.tagName == "script") {
4040
return html`<${ScriptElement} model=${model} />`;
41+
} else if (model.tagName == "input") {
42+
return html`<${InputElement} model=${model} />`;
4143
} else if (model.importSource) {
4244
return html`<${ImportedElement} model=${model} />`;
4345
} else {
@@ -68,6 +70,39 @@ function StandardElement({ model }) {
6870
);
6971
}
7072

73+
function InputElement({ model }) {
74+
const ref = React.useRef();
75+
const layoutContext = React.useContext(LayoutContext);
76+
77+
const props = createElementAttributes(model, layoutContext.sendEvent);
78+
const value = props.value;
79+
delete props.value;
80+
81+
console.log(value);
82+
React.useEffect(() => {
83+
if (value !== undefined) {
84+
ref.current.value = value;
85+
}
86+
}, [ref.current, value]);
87+
88+
// Use createElement here to avoid warning about variable numbers of children not
89+
// having keys. Warning about this must now be the responsibility of the server
90+
// providing the models instead of the client rendering them.
91+
return React.createElement(
92+
model.tagName,
93+
{
94+
...props,
95+
ref: (target) => {
96+
ref.current = target;
97+
},
98+
},
99+
...createElementChildren(
100+
model,
101+
(model) => html`<${Element} key=${model.key} model=${model} />`
102+
)
103+
);
104+
}
105+
71106
function ScriptElement({ model }) {
72107
const ref = React.useRef();
73108
React.useEffect(() => {

src/client/packages/idom-client-react/src/element-utils.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ function createEventHandler(eventName, sendEvent, eventSpec) {
3939
if (typeof value === "object" && value.nativeEvent) {
4040
if (eventSpec["preventDefault"]) {
4141
value.preventDefault();
42-
} else if (eventName === "onChange") {
43-
value.nativeEvent.target.value = value.target.value;
4442
}
4543
if (eventSpec["stopPropagation"]) {
4644
value.stopPropagation();

0 commit comments

Comments
 (0)