Help us understand the problem. What is going on with this article?

Custom PropTypes Validator

More than 3 years have passed since last update.

prop-typesが提供しているものでも十分だが、もっと細かいTypecheckingが必要な場合がある。
custom validatorを作ってみよう。

custom validatorを作るための原則

  • validatorはpropertyのリスト、検証したいproperty名、コンポーネント名を引数として持つ関数だ。
  • validatorは検証したpropertyが有効な場合は何も返さないが、間違った場合はErrorのインスタンスを返さなければならない。

今度作りたいcustom validatorは

propertyが必須で、値が文字列である。
文字列の長さは80文字以内でなければならない。

const customPropType = (props, propName, componentName) => {
  if (props[propName]) {
    const value = props[propName];
    if (typeof value !== 'string' || value.lenght > 80) {
      return new Error(
        `${propName} in ${componentName} is longer than 80 characters`,
      )
    }
  }
};

動作には問題ないが、eslintエラーが出る。

propType "title" is not required, but has no corresponding defaultProp declaration. (react/require-default-props)

そもそも検証の対象になるpropertyは必須だった。
isRequiredを付けるか、defaultPropで指定しないと解決できない。
isRequiredを付けると、eslintエラーは消えたが、browserのほうでエラーが表示された。
custom validatorを作る場合は、isRequiredについても別途に実装しなければならないようだ。
Reactのガイドにはcustom validatorについて上記のような一般的な例を紹介しているだけで、isRequiredは言及されてない。

同じ悩みを持っている人はどこにもいる。
案外に重要な話だ。すぐ解決できない場合はぐぐってみよう。
ぐぐっても解決できない場合は、githubのissuesやwikiとかで探してみよう。(stackoverflowよりマシだ。)
次はreactのgithub issuesから見つけたものだ。
結構よかったので、紹介する。

// This is a factory function (also called a higher-order function)
function createCustomPropType(isRequired) {
  // The factory returns a custom prop type
  return function(props, propName, componentName) {
    const prop = props[propName];
    if (prop == null) {
      // Prop is missing
      if (isRequired) {
        // Prop is required but wasn't specified. Throw an error.
        throw new Error();
      }
      // Prop is optional. Do nothing.
    } else {
      // Put your validation logic here...
    }
  }
}

// Using the factory, create two different versions of your prop type
const customPropType = createCustomPropType(false);
customPropType.isRequired = createCustomPropType(true);

// Now this will work:
MyComponent.propTypes = {
  optional: customPropType,
  required: customPropType.isRequired,
};

custom validatorとして、factory functionを作っている。
propertyが必須なので、optionalは意味がない。
注目するのはrequiredのところだ。
早速、必要なvalidationを入れて確認した。
動作には問題ない。
しかし、いくつかeslintエラーが出たので次のように修正した。

function createCustomPropType(isRequired) {
  return (props, propName, componentName) => {
    const prop = props[propName];
    if (prop == null) {
      if (isRequired) {
        return new Error(
          `The prop \`${propName}\` is marked as required in \`${componentName}\`, but its value is \`undefined\`.`,
        );
      }
    } else if (typeof prop !== 'string' || prop.length > 80) {
      return new Error(
        `${propName} in ${componentName} is longer than 80 characters`,
      );
    }
    return null;
  };
}

const customPropType = createCustomPropType(false);
customPropType.isRequired = createCustomPropType(true);

MyComponent.propTypes = {
  required: customPropType.isRequired,
};

検証しているpropertyが文字列ではない場合、そして文字列の長さが80を超えるとbrowserでエラーが表示される。
isRequiredを付けた場合は、該当propertyが存在しないとbrowserでエラーが表示される。
かなりいい感じ〜:thumbsup:

park-jh
プルスタックエンジニアになれるまで頑張ろう。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした