Skip to content

Instantly share code, notes, and snippets.

@oxyflour
Created August 29, 2020 12:50
Show Gist options
  • Select an option

  • Save oxyflour/1d7f6ab5268d8d9578f96c9ef59f848f to your computer and use it in GitHub Desktop.

Select an option

Save oxyflour/1d7f6ab5268d8d9578f96c9ef59f848f to your computer and use it in GitHub Desktop.
async generator react
<html>
<body>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="index.jsx" type="text/babel"></script>
</body>
</html>
function sleep(t) {
return new Promise(resolve => setTimeout(resolve, t))
}
async function delayed(x, t = 2000) {
await sleep(t)
return x
}
const createElement = React.createElement.bind(React)
React.createElement = (tag, props, ...children) => ({ tag, props, children })
function render(elem, container) {
async function show() {
ReactDOM.render(await convert(elem), container)
}
async function convert(elem) {
let { tag, props, children } = elem
if (typeof tag === 'string') {
children = await Promise.all(children.map(child => convert(child)))
return createElement(tag, props, ...children)
} else if (typeof tag === 'function') {
if (!elem.iter) {
elem.iter = tag(async val => {
elem.next = await elem.iter.next(val)
await show()
}, props, ...children)
elem.next = await elem.iter.next()
}
return await convert(elem.next.done ? elem.ret : (elem.ret = elem.next.value))
} else if (Array.isArray(elem)) {
return await Promise.all(elem.map(el => convert(el)))
} else {
return elem
}
}
return show()
}
async function *Counter(next, props) {
let count = 1
while (true) {
count = yield <div key={ props.key }>
<button onClick={ () => next(count + 1) }>+</button>
[ { count } ]
<button onClick={ () => next(count - 1) }>-</button>
</div>
}
}
async function *App(next) {
setTimeout(next)
yield <div>loading...</div>
try {
const arr = await delayed([0, 1])
yield <div>
{ arr.map(val => <Counter key={ val } />) }
<button onClick={ next }>next</button>
</div>
} catch (err) {
yield <div style={{ color: 'red' }}>error { err.message }</div>
}
}
const div = document.createElement('div')
document.body.append(div)
render(<App />, div)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment