Last active
June 18, 2018 07:37
-
-
Save artalar/f762c65f68565e8690daa1a8dc256891 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable */ | |
/****************************************** | |
~/form/address.jsx | |
*/ | |
import { service } from '~/service.js'; | |
import { workflow } from './workflow.js'; | |
export const Autocomplete = service.connect([workflow, 'address'])( | |
({ value, suggestions, onChange }) => ( | |
<Autocomplete name="address" value={value} suggestions={suggestions} onChange={onChange} /> | |
), | |
); | |
/****************************************** | |
~/form/workflow.js | |
*/ | |
import { path } from 'pathon'; | |
function* initiate(service) { | |
const { AUTOCOMPLETE_STATES } = yield service.reference; | |
const initialState = { | |
address: '', | |
suggestions: { address: AUTOCOMPLETE_STATES.NONE }, | |
}; | |
return { | |
...this, | |
private: { | |
...this.private, | |
state: path('form', initialState), | |
}, | |
}; | |
} | |
// `service` - global shared services; | |
// `this` - local domain services; | |
function* change(payload, service) { | |
const { state } = this.private; | |
const { dom, debounce, reference, all, api, preventRaceCondition, notification } = service; | |
const { name, value } = yield dom.fromEvent(['name', 'value'], payload); | |
yield () => state.path(name).set(value); | |
if (name !== 'address') return; | |
yield () => debounce(change, 300); | |
const suggestions = yield () => state.path('suggestions').path(name); | |
const { AUTOCOMPLETE_STATES } = yield reference; | |
yield () => suggestions.set(AUTOCOMPLETE_STATES.LOADING); | |
try { | |
const [list] = yield all([() => api.address.get(value), () => preventRaceCondition(change)]); | |
yield () => suggestions.set(list); | |
} catch (error) { | |
yield () => notification.error(error); | |
yield () => suggestions.set(AUTOCOMPLETE_STATES.NONE); | |
// `throw` for `onError` handler | |
return; | |
} | |
} | |
const connect = { | |
*address({ watch, unwatch }, service) { | |
const { state, change: onChange } = this.private; | |
const address = state.path('address'); | |
const suggestions = state.path('suggestions').path('address'); | |
unwatch(address.watch(value => watch({ value }))); | |
unwatch(suggestions.watch(suggestions => watch({ suggestions }))); | |
return { | |
value: address, | |
suggestions, | |
onChange, | |
}; | |
}, | |
}; | |
// domain handler | |
// for example, usually useful default handler from root workflow | |
function* onError({ error, lastPayload }, service) { | |
yield () => this.state.reset(initialState); | |
} | |
const log = ({ name, payload, isError }) => console[isError ? 'error' : 'log'](name, payload); | |
export const workflow = { | |
name: 'form', | |
initiate, | |
private: { | |
change, | |
}, | |
public: { | |
connect, | |
}, | |
handler: { | |
onError, | |
log, | |
}, | |
}; | |
/****************************************** | |
~/service.js - root | |
*/ | |
import { createService } from 'bus'; | |
import { workflow as formWorkflow } from './form/workflow'; | |
export const service = createService(); | |
service.register({ | |
form: formWorkflow, | |
/* | |
connect, dom, debounce, reference, api, preventRaceCondition, notification | |
*/ | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment