2015-07-01 11 views
6

Czy istnieje sposób, aby mieć wiele walidacji na jednym wniosku za pomocą React.PropTypes. w szczególności chcesz połączyć niestandardową walidację i walidację towaru.Wiele poprawności na React PropTypes

Mam dwa rekwizyty, obiekt options i ciąg value. chcę sprawdzić, czy props.value jest ciągiem, ale także kluczem na obiekcie. przy użyciu coffeescript wygląda to następująco:

propTypes: 
    options: React.PropTypes.Object.isRequired 
    value: (props, propName, componentName) -> 
    unless props[propName] of props.options 
     new Error('my custom message') 

działa to świetnie, ale chcę również, aby moja wartość była typu ciąg. Jestem pewien, że mogę ręcznie trzymać się tej walidacji w funkcji niestandardowej bez problemu, ale najlepiej, chciałbym tylko użyć React.PropTypes.string.isRequired. Próbowałem po prostu wstawienie go do funkcji niestandardowej i wykonanie go, ale to nie zadziałało. następuje nie działa albo:

value: React.PropTypes.string.isRequired && (props, propName, componentName) -> 
    unless props[propName] of props.options 
     new Error('my custom message') 

czy istnieje sposób, aby dostać tę pracę za pomocą reaguje zbudowany w walidatora lub jest przepisywanie go w mojej funkcji jedyną opcją?

Odpowiedz

2

Od strony Reusable Components w 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('Validation failed!'); 
    } 
} 

Więc propType zwraca nic lub obiektu o błędzie. Możemy napisać funkcję "wszystkie", która pobiera dwa typy propTes i scala wynik.

const allPropTypes = (...types) => (...args) => { 
    const errors = types.map((type) => type(...args)).filter(Boolean); 

    // no errors? cool! 
    if (errors.length === 0) return; 

    // collect the messages and join them together 
    const message = errors.map((e) => e.message).join('\n'); 
    return new Error(message); 
}; 

Następnie można użyć tego do potwierdzenia wielu typów PropTes.

propTypes = { 
    foo: allPropTypes(
    PropTypes.string.isRequired, 
    (props, propName, componentName) => props.options && props.options[props[propName]] 
     ? undefined 
     : new Error(
      `${componentName}: expected prop ${propName}="${prop[propName]}"` 
      + `to be a key of prop "options" ` 
      + `(one of ${Object.keys(props.options).join(', ')})` 
     ) 
) 
} 

Uwaga: nic z tego nie jest testowane, ale nie ma błędów w składni! Możesz skompilować go do es3 z Babel lub przekonwertować go do CS ręcznie.

+0

Jestem świadomy, że mogę nadal dodawać rzeczy do mojej niestandardowej walidacji. najprawdopodobniej można by to uzyskać, wykonując 'return new Error ('msg'), chyba że typeof rekwizyty [propName] == 'string'', ale pytam, czy jest bardziej formalny sposób, który reaguje (np. użyj 'React.PropTypes.string.isRequired'), ponieważ jest bardziej zrozumiały co do tego, co się dzieje – PhilVarg

+0

@PhilVarg potrzebujesz stworzyć swój własny typ. Żaden z wbudowanych typów PropTypów nie wykonuje żadnych sprawdzeń krzyżowych, o ile wiem. Możesz umieścić go w module gdzieś i zaimportować go z ładną nazwą, a nawet część 'options' może być dynamiczna, np. 'foo: isKeyOfProp (" opcje ")'. – FakeRainBrigand

0

Jeśli podążasz za linkiem this, Ian Thomas wyjaśnia użycie metody createChainableTypeChecker, która reaguje, ale nie eksportuje jej jako części modułu propTypes. Artykuł zawiera jasne wyjaśnienie, w jaki sposób można użyć tego samego kodu do połączeń sprawdzania poprawności łańcucha:

function createChainableTypeChecker(validate) { 
    function checkType(isRequired, props, propName, componentName, location) { 
    componentName = componentName || ANONYMOUS; 
    if (props[propName] == null) { 
     var locationName = ReactPropTypeLocationNames[location]; 
     if (isRequired) { 
     return new Error(
      ("Required " + locationName + " `" + propName + "` was not specified in ") + 
      ("`" + componentName + "`.") 
     ); 
     } 
     return null; 
    } else { 
     return validate(props, propName, componentName, location); 
    } 
    } 

    var chainedCheckType = checkType.bind(null, false); 
    chainedCheckType.isRequired = checkType.bind(null, true); 

    return chainedCheckType; 
} 
+0

Gdzie mogę uzyskać ReactPropTypeLocationNames? – Shanimal

Powiązane problemy