Created
March 30, 2016 19:03
-
-
Save brianmcallister/fd0e4ec1947fcb860b19b81d7fbfbf83 to your computer and use it in GitHub Desktop.
Override React's `isRequired` prop type validation. Allows you to express "If not X, than A, B, C".
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
// Override the `isRequired` validation of a list of props for another, single | |
// prop. For example, if you had a number of props used to generate a URL path, | |
// you could require all of them *unless* a full path was passed as a prop. | |
// | |
// @param {array} toOverride - Array of strings to 'override', or ignore. | |
// @param {function} [type] - PropType validation function. Optional. | |
// @param {boolean} [required] - Validate the prop as required. Optional. | |
// | |
// @returns {function} Callback function for custom prop validation. | |
// See the `customProp` in http://bit.ly/1nhwVQ3. | |
export default function overridePropValidation(toOverride, type, required) { | |
return (props, name, component, location) => { | |
// If the prop wasn't passed, validate all other keys were. | |
if (!props[name]) { | |
// If not, throw an error. | |
if (!hasAllKeys(props, toOverride)) { | |
return new Error( | |
`${component} requires either a ${name} prop, or the following | |
attributes as props: (${toOverride.join(', ')}).` | |
); | |
} | |
return null; | |
} | |
if (!type) { | |
return null; | |
} | |
if (required) { | |
return type.isRequired(props, name, component, location); | |
} | |
return type(props, name, component, location); | |
}; | |
} | |
// Check if a `list` has all `keys`. | |
// | |
// @param {object|array} list - List of keys, or array. | |
// @param {array} keys - Array of keys to check exist in `list`. | |
// | |
// @returns {boolean} `true` if all keys exist, `false` if they don't. | |
const hasAllKeys = (list, keys) => { | |
// Assume if `list` isn't an array, it's an object. | |
if (toString.call(list) !== '[object Array]') { | |
list = Object.keys(list); | |
} | |
for (let key of keys) { | |
if (list.indexOf(key) === -1) { | |
return false; | |
} | |
} | |
return true; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment