Immutable form state management for ReactJS
npm i --save @trioxis/immutable-react-formImmutable form is a Higher Order Component (HOC), used like so:
importReactfrom'react';import{LocalStateForm}from'@trioxis/immutable-react-form';import{Map}from'immutable';functionMyForm(props){const{
form
}=props;return<formonSubmit={form.submission.submit}><inputtype='text'value={form.model.get('name')}onChange={(e)=>update(form.model.set('name',e.target.value))}/></form>}LocalStateForm(// A function which takes props, and returns the form's modelprops=>({name: ''}),// The validation function. See Validation below for details// This is a simple default()=>newMap({}),// The submission function. Should return a promise(model,props)=>Promise.resolve())(MyForm)Full props are as follows:
const{form:{
model,// Immutable JS
update,// (model)=>void (expects entire model)meta:{
dirty // bool (whether or not the model has changed)},validation:{
get,// (keyPath)=>{valid:bool,message:string>}
isValid,//bool},submission:{
submit,// (event)=>void
loading,// boollastSubmission: {
success,// bool
error // error}}}}=props;Validation function must return an (Immutable JS) Map where each key is a path to the validation object.
If a path is not defined, it is assumed valid.
Example:
functionvalidateForm(model){returnnewMap({
...(model.get('name').split(' ').length!==2)&&{name: {valid:false,message:'Apparently you should only have 2 names'}},
...!model.get('name')&&{name: {valid:false,message:'Name is required'}},
...(model.get('experience').size<3)&&{experience : {valid:false,message:'Please write 3 or more things'}},
...(model.get('experience').map((exp,i)=>newMap({item:exp,index:i})).filter(exp=>!(['Education','Job'].includes(exp.getIn(['item','type'])))).reduce((acc,curr,i)=>({
...acc,[`experience.${curr.get('index')}.type`]: {valid:false,message:'Can be "Education" or "Job"'}}),{}))})}(props)=><inputtype='submit'value={props.form.submission.loading ? 'Submitting...' : 'Submit'}disabled={(!props.form.meta.dirty||!props.form.validation.isValid||props.form.submission.loading)}/>