Как стать автором
Поиск
Написать публикацию
Обновить

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, извлекаем сообщения ошибок и вуаля — обработка ошибок готова!
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.