Pull to refresh

ErrorBoundary для неверных props, или как я хакнул prop-types

Не так давно мой техлид на проекте сказал о том, что есть необязательная, но весьма специфичная и в то же время интересная задача: нужно сделать Error Boundary для обработки неверно пришедших props в компонент. Я на радостях за нее взялся с уверенностью, что в документации уже точно есть такое решение.

Думаю, вы уже поняли, что не все оказалось так просто.

Несколько часов серфинга не дали абсолютно никаких результатов и я осознал, что мне придется лезть внутрь пакета prop-types.

На самом деле было сложно понять, что там творится внутри, но все-таки мое внимание кое-что привлекло, а именно константа ReactPropTypesSecret в одноименном файле:

var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';

Звучит угрожающе, правда?

Я долго не мог понять, что же значит эта константа. Сначала я подумал, что это просто какая-то забавная пасхалка от Facebook, но не тут-то было, у нее и в самом деле есть смысл!
В файле factoryWithTypeCheckers.js я нашел функцию checkType, которая по сути является тем самым валидатором, который кидает warning в консоль, если в компонент пришли неверные props:

function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {

Обратите внимание на последний аргумент! Если последним аргументом в эту функцию передать константу из файла ReactPropTypesSecret.js, то вместо warning в консоль функция будет возвращать объект ошибки неверных props, либо null, если все верно.
И уже это можно использовать для того, чтобы создать компонент-обработчик ошибок для неверных props.

На основе полученных мной знаний я создал простейший HOC, который можно использовать как Error Boundary для любого компонента. Выглядит он так:

import React from ‘react’;
import SECRET from ‘prop-types/lib/ReactPropTypesSecret’;

const propTypesChecker = (Component) => (props) => {
  const analysis = Object.keys(Component.propTypes).map((key) => {
    // Здесь мы получим одну из функций-валидаторов. Например, PropTypes.number
    const validator = Component.propTypes[key]; 
    // Вызов валидатора с передачей константы-секрета последним аргументом
    return validator(props, key, Component.name, ‘’, null, SECRET);
  });
  // Извлекаем сообщения об ошибках
  const errors = analysis.filter((error) => error !== null).map((error) => error.message); 
  const arePropsValid = errors.length === 0;
  //  Компонент/элемент, переданный в props, который должен отобразиться в случае неверно пришедших props
  const ErrorBoundary = props.errorBoundary; 

  return (
    arePropsValid
      ? <Component {…props} />
      : <ErrorBoundary errors={errors} />
  );
};

export default propTypesChecker;

Сначала мы вызываем для каждого прописанного propType у компонента функцию-валидатор, затем убираем из полученного массива null, извлекаем сообщения ошибок и вуаля — обработка ошибок готова!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.
Change theme settings