bestsource

동적 키가 있는 개체의 PropTypes 검사

bestsource 2023. 2. 13. 20:36
반응형

동적 키가 있는 개체의 PropTypes 검사

React에는 PropTypes를 사용하여 프로포트의 가치를 확인하는 다양한 방법이 있습니다.제가 자주 쓰는 건React.PropTypes.shape({...})그런데 얼마 전에 동적 키/값을 내장한 오브젝트를 발견했습니다.각 키는 문자열(기존 형식)이어야 하며 각 값은 int여야 합니다.커스텀 소품 검증 기능을 사용하더라도 소품의 키를 알고 있다고 가정합니다.PropTypes를 사용하여 객체/쉐이프의 키와 값이 모두 올바른지 확인하려면 어떻게 해야 합니까?

...
someArray: React.PropTypes.arrayOf(React.PropTypes.shape({
  // How to specify a dynamic string key? Keys are a date/datetime string
  <dynamicStringKey>: React.PropTypes.number
}))
...

다시 한 번 말씀드리지만최소한 각 키의 값이 숫자인지 확인하고 싶다.또한 키 자체가 올바른 형식의 문자열인지 확인할 수 있으면 좋겠습니다.

값만 검증하려면React.PropTypes.objectOf.

...
someArray: React.PropTypes.arrayOf(
  React.PropTypes.objectOf(React.PropTypes.number)
)
...

주의: 이 답변은 현재 React 버전이 0.14.3이었던 2015년에 작성되었습니다.현재 사용 중인 React 버전에 적용되거나 적용되지 않을 수 있습니다.

그것은 재미 있는 질문입니다.질문하신 내용에 따르면 Prop Validation 문서에서 사용자 지정 유형 검사기에 대한 내용을 읽은 것 같습니다.후세를 위해 여기서 재현하겠습니다.

// 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('Validation failed!');
  }
}

타입 체커를 실장할 때는 가능한 한 리액트의 내장 타입 체커를 사용하고 싶습니다.값이 숫자인지 확인하고 싶기 때문에 다음을 사용해야 합니다.PropTypes.number그런 것 같죠?그냥 이렇게 하면 좋을 것 같아요.PropTypes.number('not a number!')적절한 에러를 얻을 수 있습니다만, 유감스럽게도, 그것보다 조금 더 문제가 있습니다.첫 번째 목적지는...

유형 검사기 작동 방식

다음은 유형 검사기의 함수 시그니처입니다.

function(props, propName, componentName, location, propFullName) => null | Error

보시다시피 모든 소품이 첫 번째 인수로 통과되고, 두 번째 인수로 테스트되는 소품의 이름이 통과됩니다.마지막 3개의 인수는 유용한 오류 메시지 출력에 사용되며 임의입니다.componentName자동 조절이 가능합니다. location의 하나가 될 것이다.'prop','context', 또는'childContext'(우리의 관심사는'prop', 및propFullName네스트 소품들을 다룰 때 사용합니다.someObj.someKey.

이 지식을 바탕으로 타입 체커를 직접 호출할 수 있습니다.

PropTypes.number({ myProp: 'bad' }, 'myProp');
// => [Error: Invalid undefined `myProp` of type `string` supplied
//     to `<<anonymous>>`, expected `number`.]

봤지? 모든 인수가 없으면 별로 쓸모가 없어이것이 더 낫다:

PropTypes.number({ myProp: 'bad' }, 'myProp', 'MyComponent', 'prop')
// => [Error: Invalid prop `myProp` of type `string` supplied
//     to `MyComponent`, expected `number`.]

어레이 유형 검사기

를 「」에 「 Checker 。PropTypes.arrayOf각 어레이 요소에 대해 호출되며 처음 두 개의 인수는 각각 어레이 자체와 현재 요소의 인덱스가 됩니다.이제 유형 검사기를 스케치할 수 있습니다.

function validArrayItem(arr, idx, componentName, location, propFullName) {
  var obj = arr[idx];

  console.log(propFullName, obj);

  // 1. Check if `obj` is an Object using `PropTypes.object`
  // 2. Check if all of its keys conform to some specified format
  // 3. Check if all of its values are numbers

  return null;
}

까지 그것은 항상 이다.null만, 는 ()을 나타냄)를 수 있습니다.console.log같이 할 수 .이제 다음과 같이 테스트할 수 있습니다.

var typeChecker = PropTypes.arrayOf(validArrayItem);
var myArray = [ { foo: 1 }, { bar: 'qux' } ];
var props = { myProp: myArray };

typeChecker(props, 'myProp', 'MyComponent', 'prop');
// -> myProp[0] { foo: 1 }
//    myProp[1] { bar: 'qux' }
// => null

바와 같이, '우리'는 '우리'입니다.propFullNamemyProp[0]첫 번째 아이템과myProp[1]1월 1일

이제 함수의 세 부분을 구체화해 보겠습니다.

1. 1. 1obj는 을 사용하는 입니다.PropTypes.object

이것이 가장 쉬운 부분입니다.

function validArrayItem(arr, idx, componentName, location, propFullName) {
  var obj = arr[idx];
  var props = {};
  props[propFullName] = obj;

  // Check if `obj` is an Object using `PropTypes.object`
  var isObjectError = PropTypes.object(props, propFullName, componentName, location);
  if (isObjectError) { return isObjectError; }

  return null;
}

var typeChecker = PropTypes.arrayOf(validArrayItem);
var props = { myProp: [ { foo: 1 }, 'bar' ] };
typeChecker(props, 'myProp', 'MyComponent', 'prop');
// => [Error: Invalid prop `myProp[1]` of type `string` supplied to
//     `MyComponent`, expected `object`.]

완벽해!다음...

2. 모든 키가 지정된 형식에 적합한지 확인합니다.

질문에서 "각 키는 문자열이어야 합니다"라고 말했지만 JavaScript의 모든 객체 키는 문자열이므로 임의로 키가 모두 대문자로 시작하는지 테스트해야 합니다.이를 위한 사용자 지정 유형 체커를 만듭니다.

var STARTS_WITH_UPPERCASE_LETTER_EXPR = /^[A-Z]/;

function validObjectKeys(props, propName, componentName, location, propFullName) {
  var obj = props[propName];
  var keys = Object.keys(obj);

  // If the object is empty, consider it valid
  if (keys.length === 0) { return null; }

  var key;
  var propFullNameWithKey;

  for (var i = 0; i < keys.length; i++) {
    key = keys[i];
    propFullNameWithKey = (propFullName || propName) + '.' + key;

    if (STARTS_WITH_UPPERCASE_LETTER_EXPR.test(key)) { continue; }

    return new Error(
      'Invalid key `' + propFullNameWithKey + '` supplied to ' +
      '`' + componentName + '`; expected to match ' +
      STARTS_WITH_UPPERCASE_LETTER_EXPR + '.'
    );
  }

  return null;
}

자체적으로 테스트할 수 있습니다.

var props = { myProp: { Foo: 1, bar: 2 } };
validObjectKeys(props, 'myProp', 'MyComponent', 'prop');
// -> myProp.Foo Foo
//    myProp.bar bar
// => [Error: Invalid key `myProp.bar` supplied to `MyComponent`;
//     expected to match /^[A-Z]/.]

좋습니다! 이제 이 기능을validArrayItem「이것들」은 다음과 같습니다.

function validArrayItem(arr, idx, componentName, location, propFullName) {
  var obj = arr[idx];
  var props = {};
  props[propFullName] = obj;

  // Check if `obj` is an Object using `PropTypes.object`
  var isObjectError = PropTypes.object(props, propFullName, componentName, location);
  if (isObjectError) { return isObjectError; }

  // Check if all of its keys conform to some specified format
  var validObjectKeysError = validObjectKeys(props, propFullName, componentName);
  if (validObjectKeysError) { return validObjectKeysError; }

  return null;
}

테스트해 보세요.

var props = { myProp: [ { Foo: 1 }, { bar: 2 } ] };
var typeChecker = PropTypes.arrayOf(validArrayItem);
typeChecker(props, 'myProp', 'MyComponent', 'prop');
// -> myProp[0].Foo Foo
//    myProp[1].bar bar
// => [Error: Invalid key `myProp[1].bar` supplied to `MyComponent`;
//     expected to match /^[A-Z]/.]

그리고 마지막으로...

3. 모든 값이 수치인지 확인한다.

다', '빌트인하다', '빌트인하다', '빌트인하다', '빌트인하다', '다', '빌트인하다'를 할 수 있기 에 많은 작업을 할 가 없습니다PropTypes.objectOf:

// Check if all of its values are numbers
var validObjectValues = PropTypes.objectOf(PropTypes.number);
var validObjectValuesError = validObjectValues(props, propFullName, componentName, location);
if (validObjectValuesError) { return validObjectValuesError; }

아래에서 테스트해 보겠습니다.

이젠 다 함께.

마지막 코드는 다음과 같습니다.

function validArrayItem(arr, idx, componentName, location, propFullName) {
  var obj = arr[idx];
  var props = {};
  props[propFullName] = obj;

  // Check if `obj` is an Object using `PropTypes.object`
  var isObjectError = PropTypes.object(props, propFullName, componentName, location);
  if (isObjectError) { return isObjectError; }

  // Check if all of its keys conform to some specified format
  var validObjectKeysError = validObjectKeys(props, propFullName, componentName);
  if (validObjectKeysError) { return validObjectKeysError; }

  // Check if all of its values are numbers
  var validObjectValues = PropTypes.objectOf(PropTypes.number);
  var validObjectValuesError = validObjectValues(props, propFullName, componentName, location);
  if (validObjectValuesError) { return validObjectValuesError; }

  return null;
}

테스트를 위한 간단한 편의 함수를 작성하고 몇 가지 데이터를 제공합니다.

function test(arrayToTest) {
  var typeChecker = PropTypes.arrayOf(validArrayItem);
  var props = { testProp: arrayToTest };
  return typeChecker(props, 'testProp', 'MyComponent', 'prop');
}

test([ { Foo: 1 }, { Bar: 2 } ]);
// => null

test([ { Foo: 1 }, { bar: 2 } ]);
// => [Error: Invalid key `testProp[1].bar` supplied to `MyComponent`;
//     expected to match /^[A-Z]/.]

test([ { Foo: 1 }, { Bar: false } ]);
// => [Error: Invalid prop `testProp[1].Bar` of type `boolean` supplied to
//     `MyComponent`, expected `number`.]

됐다!이제 내장형 체커와 마찬가지로 React 컴포넌트에서도 사용할 수 있습니다.

MyComponent.propTypes = {
  someArray: PropTypes.arrayOf(validArrayItem);
};

물론 좀 더 의미 있는 이름을 붙이고 자체 모듈로 옮기는 것이 좋습니다.

나에게 있어서 문제는...

  • 개체에 동적 키가 있음(확인하지 않음)
  • 값은 고정된 데이터 구조를 가지고 있습니다(확인하고 싶습니다).
  • 기본 데이터 구조의 형태를 알고 확인할 수 있습니다.

    // An object with property values of a certain shape
    optionalObject: PropTypes.objectOf(
      PropTypes.shape({
        color: PropTypes.string.isRequired,
        fontSize: PropTypes.number
      })
    );
    

제 는 누락된 이 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.PropTypes.objectOf여기서 동적 키를 사용하여 모든 유형의 구조물을 만들 수 있습니다., 「 」와해 주세요.PropTypes.oneOfType우우유유 유다다다다다

함수를 전달하여 자체 검증기를 만들 수 있습니다.

것은, 을 참조하십시오.customProp 여기 있습니다.

도 할 수 것 요.React.PropTypes.arrayOf(customValidator).

찾으시는 검증자는 다음과 같습니다.

function objectWithNumericKeys(obj) {
  if (Object.keys(obj).some(key => isNaN(key)))
     return new Error('Validation failed!');
}

언급URL : https://stackoverflow.com/questions/34362898/proptypes-check-of-object-with-dynamic-keys

반응형