简体   繁体   中英

How to manually call custom PropType validators in React v16

I have a use case where I need to write a custom React PropType validator. Within that checker I want to do two things: 1) validate that the prop names inside the object, which are dynamically generated, are all md5 hashes, and 2) validate the "shape" of the object connected to each prop.

Question #1 I have figured out; #2 is eluding me a bit. Here's some code to illustrate:

Say I have an object like this:

{
  key1: {
    byHash: {
      '<some md5 hash>': { ... }
    }
  },
  key2: {
    byHash: {
      '<some md5 ash>': { ... }
    }
  }
}

When checking this object I want to make sure that the keys are indeed md5 hashes, and then I want to ensure the correctness of the keys and their values in each of the objects assigned to key1 and key2 . Let's say, in addition, I've created a validator function like so:

const validObjShape = PropTypes.shape({
  someString: PropTypes.string.isRequired,
  someBoolean: PropTypes.bool
});

Then I write my custom validator function:

const validCustomProp  = (props, propName, componentName) => {
  const obj = props[propName];

  if (!isObject(obj)) {
    return new Error(
      //eslint-disable-next-line
      'Invalid prop `' + propName + '`of type `' + typeof obj + '` supplied to ' +
      '`' + componentName + '`, expected an object.'
    );
  }

  if (isEmpty(obj)) {
    return null;
  }

  forEach(obj, (v, k) => {
    const isMD5 = (/[a-fA-F0-9]{32}/).test(k);

    if (!isMD5) {
      throw new Error(
        //eslint-disable-next-line
        'Invalid dynamic key on `' + propName + '`. All keys ' +
        'on this object should be md5 hashes, but we found `' + k + '` instead.'
      );
    }
  });

  // Here I want to somehow validate each object on `obj`. Something like:
  // forEach(obj, (v, k) => { 
  //   const err = validObjShape(props[propName], k, componentName);
  //   if (err) {
  //     // throw some err...
  //   }
  // }

  return null;
};

My question -- as noted in-line above -- can I use the validObjShape that I created above to validate the shape of the objects nested within obj . I think that this calling of a validator fn directly will be disallowed in v16 of React (see this post ). So how can this now be achieved?

Using PropTypes directly from React is deprecated - not the use of PropTypes themselves.

As it says in the docs, declaring PropTypes is fine , just use the prop-types library instead.

So,

const apiShape = React.PropTypes.shape({
  body: customValidator,
  statusCode: React.PropTypes.number.isRequired
}).isRequired;

simply changes to

import PropTypes from 'prop-types';
const apiShape = React.PropTypes.shape({
  body: customValidator,
  statusCode: PropTypes.number.isRequired
}).isRequired;

And the customValidator doesn't have to change.

You can verify this yourself in the source: ElementCreation => ElementValidation in DEV mode => Validating prop types => calling checkPropTypes which has simply been moved here

React strongly believes in type safety and deprecating PropTypes altogether seems very unlikely. It is still present in the docs (from the master)

Calling validator functions as you mentioned is now deprecated too

Note from the docs

This is new behavior, and you will only encounter it when you migrate from React.PropTypes to the prop-types package.

So the following is deprecated

  Object.keys(props[propName]).forEach(k => {

    // const v = props[propName][k];
    const isMD5 = (/[a-fA-F0-9]{32}/).test(k);
    if (!isMD5) {
      return new Error(
        'Not an md5'
      );
    }

    return validObjShape(props[propName], k, componentName);
  });

Instead use checkPropTypes :

const validObjShape = PropTypes.shape({
  someString: PropTypes.string.isRequired,
  someBoolean: PropTypes.bool
});

const validCustomProp  = (props, propName, componentName) => {

  Object.keys(props[propName]).forEach(k => {

    const v = props[propName][k];
    const isMD5 = (/[a-fA-F0-9]{32}/).test(k);
    if (!isMD5) {
      return new Error(
        'Not an md5'
      );
    }

    PropTypes.checkPropTypes({ [k]: validObjShape }, { [k]: v }, propName, componentName);

  });


  return null;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM