diff options
Diffstat (limited to 'preact/demo/stateOrderBug.js')
-rw-r--r-- | preact/demo/stateOrderBug.js | 80 |
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; |