Mrr form validation example

by mikolalex

HTML

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/mrr@1.2.6/dist/bundle.js"></script>
<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

Babel + JSX

const getNameErrors = a => {
	if(a.length < 2){
		return "Name too short!";
	}
	if(a.match(/[\#\$\%\@\!\~]/)){
		return "No special symbols allowed!";
	}
	return false;
}

const getEmailErrors = a => {
	if(!a.match(/.*\@.*/)){
		return "Please enter valid email address!";
	}
	return false;
}

const and = (a, b) => a && b;
const id = a => a;
const not = a => !a;
const incr = a => a + 1;
const always = a => () => a;
const or = a => b => b || a;

const Root = mrr.withMrr({
  $init: {
    name: '',
    email: '',
    attempts: 0,
  },
  $log: true,
  $expose: ['successfulLogin'],
  successfulLogin: 'checkLoginRequest.success',
  nameError: [getNameErrors, 'name', 'submit'],
  emailError: [getEmailErrors , 'email', 'submit'],
  formValid: [(a, b) => !a && !b, 'nameError', 'emailError'],
  submission: ['split', {
		'error': not,
		'success': (valid, name, email) => valid && { name, email },
	}, '-formValid', '-name', '-email', 'submit'],
	checkLoginRequest: ['nested', (cb, { name, email }) => {
		cb('loading', true);
		fetch('/check-login?name=' + name + '&email=' + email)
		.then(res => cb('success', res.toJSON()))
		.catch(e => cb('error', e.errorMessage))
		.finally(() => cb('loading', false));
	}, 'submission.success'],
	successMessage: [always('Congratulations!'), 'checkLoginRequest.success'],
	cleanUpErrors: ['merge', 'submission.success', 'name', 'email'],
	errorsShown: ['merge', {
		'submit': always(true),
		'cleanUpErrors': always(false),
	}],
	error: ['merge', {
		'checkLoginRequest.error': or('Some backend error happened!'),
		'cleanUpErrors': always(false),
	}],
	attempts: ['merge', {
    'checkLoginRequest.error': (_, prev) => prev + 1,
		'checkLoginRequest.success': always(0),
	}, '^']
}, (state, props, $) => ( state.attempts > 10
	    ?  <div>You did too many attempts!</div>
	    : ( <form>
		  { state.successMessage && <div>{ state.successMessage}</div> }
	      Enter your name: <input value={ state.name } onChange={ $('name') } />
	      {...