Skip to content

Commit

Permalink
actually fix #684
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rmorshea committed Mar 2, 2022
1 parent c9536f6 commit 72f6081
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/source/_custom_js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions src/client/packages/idom-client-react/src/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export function Element({ model }) {
}
} else if (model.tagName == "script") {
return html`<${ScriptElement} model=${model} />`;
} else if (model.tagName == "input") {
return html`<${InputElement} model=${model} />`;
} else if (model.importSource) {
return html`<${ImportedElement} model=${model} />`;
} else {
Expand Down Expand Up @@ -68,6 +70,39 @@ function StandardElement({ model }) {
);
}

function InputElement({ model }) {
const ref = React.useRef();
const layoutContext = React.useContext(LayoutContext);

const props = createElementAttributes(model, layoutContext.sendEvent);
const value = props.value;
delete props.value;

console.log(value);
React.useEffect(() => {
if (value !== undefined) {
ref.current.value = value;
}
}, [ref.current, value]);

// Use createElement here to avoid warning about variable numbers of children not
// having keys. Warning about this must now be the responsibility of the server
// providing the models instead of the client rendering them.
return React.createElement(
model.tagName,
{
...props,
ref: (target) => {
ref.current = target;
},
},
...createElementChildren(
model,
(model) => html`<${Element} key=${model.key} model=${model} />`
)
);
}

function ScriptElement({ model }) {
const ref = React.useRef();
React.useEffect(() => {
Expand Down
2 changes: 0 additions & 2 deletions src/client/packages/idom-client-react/src/element-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ function createEventHandler(eventName, sendEvent, eventSpec) {
if (typeof value === "object" && value.nativeEvent) {
if (eventSpec["preventDefault"]) {
value.preventDefault();
} else if (eventName === "onChange") {
value.nativeEvent.target.value = value.target.value;
}
if (eventSpec["stopPropagation"]) {
value.stopPropagation();
Expand Down

0 comments on commit 72f6081

Please sign in to comment.