Created
July 23, 2015 10:29
-
-
Save junkycoder/dc8e655e0de2c38c2a2b to your computer and use it in GitHub Desktop.
Use React Prop Types to validate Immutable Records
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
import React from 'react'; | |
import Immutable from 'immutable'; | |
import {Record, Map} from 'immutable'; | |
import ImmutablePropTypes from 'react-immutable-proptypes'; | |
import merge from 'merge'; | |
export const PropTypes = merge(ImmutablePropTypes, React.PropTypes); | |
export function alteredRecord(...args) { | |
const methods = [ | |
'set', 'setIn', 'removeIn', 'remove', 'update', 'updateIn', 'merge', | |
'mergeWith', 'mergeIn', 'mergeDeep', 'mergeDeepWith', 'mergeDeepIn' | |
]; | |
const RecordPrototype = Record(...args).prototype; | |
function AlteredRecord() {} | |
let proto = AlteredRecord.prototype = Object.create(RecordPrototype); | |
proto.onAltered = function(prevRecord) {}; | |
proto._change = function(record) { | |
if(record instanceof AlteredRecord && !Immutable.is(this, record)) { | |
record.onAltered(this); | |
} | |
return record; | |
}; | |
methods.forEach(name => { | |
proto[name] = function() { | |
return this._change(RecordPrototype[name].apply(this, arguments)); | |
}; | |
}); | |
return AlteredRecord; | |
} | |
export function validRecord(propTypes, recordName) { | |
const defaults = resetProps(propTypes); | |
const AlteredRecord = alteredRecord(defaults, recordName); | |
class ValidRecord extends AlteredRecord { | |
constructor(...args) { | |
super(...args); | |
this.validate(); | |
} | |
onAltered() { | |
this.validate(); | |
} | |
validate() { | |
const name = recordName || this.constructor.name; | |
const error = validate(this.toObject(), propTypes, name); | |
if(error) { | |
console.warn(error); | |
} | |
this._validationError = error; | |
return this; | |
} | |
isValid() { | |
return !this._validationError; | |
} | |
notValid() { | |
return !this.isValid(); | |
} | |
} | |
return ValidRecord; | |
} | |
function validate(props, types, name) { | |
return PropTypes.shape(types).isRequired({props}, 'props', name); | |
} | |
function resetProps(props) { | |
return Map(props).map(() => null).toObject(); | |
} |
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
import {Record, List, Map} from 'immutable'; | |
import {validRecord, PropTypes} from '../lib/validate'; | |
import Period from './period'; | |
import DataList from './datalist'; | |
const DataSetRecord = validRecord({ | |
period: PropTypes.instanceOf(Period), | |
type: PropTypes.string.isRequired, | |
list: PropTypes.listOf(PropTypes.instanceOf(DataList)).isRequired, | |
variant: PropTypes.oneOf(['consumption', 'cost']).isRequired, | |
unit: PropTypes.string | |
}); | |
class DataSet extends DataSetRecord { | |
// Custom getters and methods | |
} | |
export default DataSet; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment