summaryrefslogtreecommitdiff
path: root/preact/demo/stateOrderBug.js
diff options
context:
space:
mode:
Diffstat (limited to 'preact/demo/stateOrderBug.js')
-rw-r--r--preact/demo/stateOrderBug.js80
1 files changed, 80 insertions, 0 deletions
diff --git a/preact/demo/stateOrderBug.js b/preact/demo/stateOrderBug.js
new file mode 100644
index 0000000..b9f333d
--- /dev/null
+++ b/preact/demo/stateOrderBug.js
@@ -0,0 +1,80 @@
+import htm from 'htm';
+import { h } from 'preact';
+import { useState, useCallback } from 'preact/hooks';
+
+const html = htm.bind(h);
+
+// configuration used to show behavior vs. workaround
+let childFirst = true;
+const Config = () => html`
+ <label>
+ <input
+ type="checkbox"
+ checked=${childFirst}
+ onchange=${evt => {
+ childFirst = evt.target.checked;
+ }}
+ />
+ Set child state before parent state.
+ </label>
+`;
+
+const Child = ({ items, setItems }) => {
+ let [pendingId, setPendingId] = useState(null);
+ if (!pendingId) {
+ setPendingId(
+ (pendingId = Math.random()
+ .toFixed(20)
+ .slice(2))
+ );
+ }
+
+ const onInput = useCallback(
+ evt => {
+ let val = evt.target.value,
+ _items = [...items, { _id: pendingId, val }];
+ if (childFirst) {
+ setPendingId(null);
+ setItems(_items);
+ } else {
+ setItems(_items);
+ setPendingId(null);
+ }
+ },
+ [childFirst, setPendingId, setItems, items, pendingId]
+ );
+
+ return html`
+ <div class="item-editor">
+ ${items.map(
+ (item, idx) => html`
+ <input
+ key=${item._id}
+ value=${item.val}
+ oninput=${evt => {
+ let val = evt.target.value,
+ _items = [...items];
+ _items.splice(idx, 1, { ...item, val });
+ setItems(_items);
+ }}
+ />
+ `
+ )}
+
+ <input
+ key=${pendingId}
+ placeholder="type to add an item"
+ oninput=${onInput}
+ />
+ </div>
+ `;
+};
+
+const Parent = () => {
+ let [items, setItems] = useState([]);
+ return html`
+ <div><${Config} /><${Child} items=${items} setItems=${setItems} /></div>
+ `;
+};
+
+export default Parent;