Max Semikin Max Semikin - 3 months ago 34
Javascript Question

React warns about passed prop with value null, where the PropType for the prop is not required

I have a component that receives error as either a string or an object with 2 required properties. But null can also be passed for this prop. In my current setup React throws a warning when null is passed:


Warning: Failed prop type: Invalid prop
error
supplied to
ErrorDialog



What shall I change for React to allow null | string | object with this shape? Thank you!

ErrorDialog.propTypes = {
onResetError: PropTypes.func.isRequired,
error: PropTypes.oneOfType([
PropTypes.shape({
id: PropTypes.number.isRequired,
defaultMessage: PropTypes.string.isRequired,
}),
PropTypes.string,
]),
};


The full code is:

import React, { PropTypes } from 'react';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import { FormattedMessage } from 'react-intl';

const ErrorDialog = ({ error, onResetError }) => {
function renderError() {
if (!error) {
return null;
} else if (typeof error === 'string') {
return error;
} else if (typeof error === 'object') {
return <FormattedMessage {...error} />;
}
return null;
}

return (
<Dialog
modal={false}
open={Boolean(error)}
actions={
<FlatButton
label="OK"
primary
onTouchTap={onResetError}
/>
}
>
{renderError()}
</Dialog>
);
};

ErrorDialog.propTypes = {
onResetError: PropTypes.func.isRequired,
error: PropTypes.oneOfType([
PropTypes.shape({
id: PropTypes.number.isRequired,
defaultMessage: PropTypes.string.isRequired,
}),
PropTypes.string,
]),
};

export default ErrorDialog;


I want to hide the dialog, when there is no error, show original string, if the error is of type string and render a translated message if a message descriptor is specified.

UPDATE: I went with the solution like this:

ErrorDialog.propTypes = {
onResetError: PropTypes.func.isRequired,
// eslint-disable-next-line consistent-return
error(props, propName, componentName) {
const prop = props[propName];
if (prop !== null &&
typeof prop !== 'string' &&
!(typeof prop === 'object' && prop.id && prop.defaultMessage)) {
return new Error(
`Invalid prop \`${propName}\` supplied to ${componentName}. Validation failed.`
);
}
},
};

Answer

Read this issue and this issue for discussions happened in the past. Just make props.error optional and check the value in your code. Otherwise, you would need to implement your own custom prop validation.

From the docs:

// You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, componentName) {
  if (!/matchme/.test(props[propName])) {
    return new Error(
      'Invalid prop `' + propName + '` supplied to' +
      ' `' + componentName + '`. Validation failed.'
    );
  }
}
Comments