Async atom example
Compare with Async redux-saga example: https://jsfiddle.net/zerkalica/3ogxg2sk/
by zerkalica
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 crossorigin src="https://unpkg.com/urc@1/dist/urc.umd.js"></script>
<script crossorigin src="https://unpkg.com/lom_atom@4/dist/lom_atom.umd.js"></script>
<div id="mount">
</div>
</body>
Babel + JSX
// @flow
const {mem, action, ReactAtom} = lom_atom
const {createConnect} = urc
const {render} = ReactDOM
const {createElement, Component} = React
// initialization
function ErrorableView({error}) {
if (error instanceof Promise) return <div>Loading...</div>
const retry = mem.retry(error)
return <div>
<pre>{error.stack.toString()}</pre>
{retry && <button onClick={retry}>Retry</button>}
</div>
}
const connect = createConnect({
BaseComponent: Component,
renderError: ErrorableView,
ReactAtom
})
class Fetcher {
@mem emulateError = false
@mem.key get(url) {
throw fetch(url)
.then(res => res.json())
.then((data) => {
if (this.emulateError) throw new Error('Fake error [500]')
return data
})
}
}
function loader(child, loading) {
try {
return child()
} catch(error) {
if (error instanceof Error) throw error
return loading
}
}
// main
const fetcher = new Fetcher()
const DOG_URL = 'https://dog.ceo/api/breeds/image/random'
class Store {
@mem get game() {
return {
url: fetcher.get(DOG_URL).message
}
}
@action reset() {
mem.cache(this.game)
}
}
const ImgView = connect(({store}) => {
return <p>
{loader(
() => <img src={store.game.url} />,
<div>Custom loading...</div>
)}
</p>
})
const HelloView = connect(({store}) =>
<div>
<button onClick={store.reset}>Show dog</button>
<input
id="emulateError"
type="checkbox"
onChange={() => fetcher.emulateError = !fetcher.emulateError}
value={fetcher.emulateError}
/>
<label htmlFor="emulateError">Emulate error</label>
<ImgView store={store} />
</div>
)
const store = new Store()
ReactDOM.render(<HelloView store={store}/>, document.getElementById('mount'));