Not to be confused with a similar question asking how to define PropTypes recursively, I'm looking for a way to pass in an argument that itself is recursive without:
Here's a simplistic example of how this might be used.
const fields = [{
accessor: 'firstName',
type: 'text',
required: true,
label: 'First Name',
placeholder: 'Enter your first name'
}];
fields.push({
accessor: 'children',
type: 'dynamicList',
label: 'Children',
fields: fields
});
return (
<Form
fields={fields}
onSave={data => console.log(data)} />
);
One hacky workaround I can think of immediately is to instead pass some sort of identifier instead that the component uses to look up some referenced prop. Is there another way, without changing React's typechecker to prevent cycles?
Note: For those interested, doing something like above works fine as far as I can tell, save for the log warnings and potentially some slight performance impact.
One way I came up with to handle prop cycles on recursive PropTypes is an adjustment to the lazy evaluation method, like so:
function lazyFunction(f, _lazyCheckerHasSeen) {
return function() {
if (_lazyCheckerHasSeen.indexOf(arguments[0]) != -1) {
return true;
}
_lazyCheckerHasSeen.push(arguments[0]);
return f().apply(this, arguments);
}
}
Used like so, for the aforementioned example:
const lazyFieldType = lazyFunction(function () {
return fieldType;
}, []);
const fieldType = PropTypes.shape({
accessor: PropTypes.string.isRequired,
type: PropTypes.oneOf(['text', 'multitext', 'checkbox', 'select', 'multiselect', 'section', 'dynamicList']).isRequired,
required: PropTypes.boolean,
label: PropTypes.string,
placeholder: PropTypes.string,
fields: PropTypes.arrayOf(lazyFieldType),
});
Form.propTypes = {
fields: PropTypes.arrayOf(fieldType),
onSave: PropTypes.func.isRequired
};