Skip to content

Instantly share code, notes, and snippets.

@junkycoder
Created July 23, 2015 10:29
Show Gist options
  • Save junkycoder/dc8e655e0de2c38c2a2b to your computer and use it in GitHub Desktop.
Save junkycoder/dc8e655e0de2c38c2a2b to your computer and use it in GitHub Desktop.
Use React Prop Types to validate Immutable Records
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();
}
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