UNPKG

react-form-with-constraints

Version:
100 lines (99 loc) 3.45 kB
import * as React from 'react'; import { instanceOf } from 'prop-types'; import { assert } from './assert'; import { FieldFeedbacks } from './FieldFeedbacks'; import { FormWithConstraints } from './FormWithConstraints'; import { withValidateFieldEventEmitter } from './withValidateFieldEventEmitter'; export var Status; (function (Status) { Status[Status["None"] = 0] = "None"; Status[Status["Pending"] = 1] = "Pending"; Status[Status["Rejected"] = 2] = "Rejected"; Status[Status["Resolved"] = 3] = "Resolved"; })(Status || (Status = {})); class AsyncComponent extends React.PureComponent { } export class Async extends withValidateFieldEventEmitter(AsyncComponent) { constructor() { super(...arguments); this.state = { status: Status.None }; this.validate = (input) => { const { form, fieldFeedbacks } = this.context; let validations; const field = form.fieldsStore.getField(input.name); if ((fieldFeedbacks.props.stop === 'first' && field.hasFeedbacks(fieldFeedbacks.key)) || (fieldFeedbacks.props.stop === 'first-error' && field.hasErrors(fieldFeedbacks.key)) || (fieldFeedbacks.props.stop === 'first-warning' && field.hasWarnings(fieldFeedbacks.key)) || (fieldFeedbacks.props.stop === 'first-info' && field.hasInfos(fieldFeedbacks.key))) { this.setState({ status: Status.None }); } else { validations = this._validate(input); } return validations; }; } getChildContext() { return { async: this }; } componentDidMount() { this.context.fieldFeedbacks.addValidateFieldEventListener(this.validate); } componentWillUnmount() { this.context.fieldFeedbacks.removeValidateFieldEventListener(this.validate); } async setStateSync(state) { return new Promise(resolve => { this.setState(state, resolve); }); } async _validate(input) { let state = { status: Status.Pending }; this.setState(state); try { const value = await this.props.promise(input.value); state = { status: Status.Resolved, value }; } catch (e) { state = { status: Status.Rejected, value: e }; } await this.setStateSync(state); return this.emitValidateFieldEvent(input); } render() { const { props, state } = this; let element = null; switch (state.status) { case Status.None: break; case Status.Pending: if (props.pending) element = props.pending; break; case Status.Resolved: if (props.then) element = props.then(state.value); break; case Status.Rejected: if (props.catch) element = props.catch(state.value); break; default: assert(false, `Unknown status: '${state.status}'`); } return element; } } Async.contextTypes = { form: instanceOf(FormWithConstraints).isRequired, fieldFeedbacks: instanceOf(FieldFeedbacks).isRequired }; Async.childContextTypes = { async: instanceOf(Async).isRequired };