Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.`
      );
    }
  },
};
like image 973
Max Semikin Avatar asked Aug 29 '16 17:08

Max Semikin


1 Answers

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.'
    );
  }
}
like image 129
goldbullet Avatar answered Nov 13 '22 07:11

goldbullet