Эталонный шаблон для неструктурированной фильтрации пропуска в компонентах более высокого порядка.

Если вы используете библиотеку компонентов более высокого порядка (HOC), например, styled-components, вы, вероятно, столкнетесь с трудностями при работе с вашими props и unknown props. Для s-c это обычно принимает форму реквизита, используемого для стилизации, и, как следствие, борьбы за предотвращение утечки на предупреждения «неизвестного» свойства DOM / React.

Учтите следующее:

import styled from "styled-components";
const SomeOtherComponent = props => <div {...props} />;
const Comp = styled(SomeOtherComponent)`
  color: ${p => p.color};
`;
<Comp color="blue">Hello world!</Comp>

При текущем состоянии вещей опора color окажется в DOM как атрибут HTML, и React будет лаять на вас, чтобы отфильтровать его. Хотя технически он не причиняет вреда, React прав, обращая ваше внимание на проблему, поскольку бесполезный мусор проходит через него.

В случае простого стилизованного компонента (например, styled.div) color будет отфильтрован с помощью некоторого кода в библиотеке, который поддерживает список всех известных имен атрибутов HTML. Это громоздкая функциональность, и это действительно обходной путь для того, что, как мне кажется, является общим ограничением в остальном фантастической парадигмы компонентов.

Для многих HOC это, вероятно, не проблема, потому что их API-интерфейс prop структурирован и состоит, возможно, из одного или двух выделенных свойств. Однако API-интерфейсы, такие как стилизованные компоненты, позволяют использовать любую опору (неструктурированную), оставляя настоящую загадку, как фильтровать вещи, которые являются реальными атрибутами и теми, которые используются только для целей «мета» стилей.

Введите временные реквизиты с префиксом $. Когда свойство имеет префикс transient, это указывает на то, что он предназначен исключительно для самого верхнего уровня компонента и не должен передаваться ниже.

import styled from "styled-components";
const SomeOtherComponent = props => <div {...props} />;
const Comp = styled(SomeOtherComponent)`
  color: ${p => p.$color};
`;
// $color will not be passed to SomeOtherComponent
<Comp $color="blue">Hello world!</Comp>

Если вы являетесь автором HOC, вы бы просто добавили такую ​​галочку при пересылке реквизита:

const props = {};
for (let key in this.props) {
  if (key[0] !== '$') props[key] = this.props[key];
}
React.createElement('whatever', props);

Предостережение: это не серебряная пуля. Если вы попадете в неудачный сценарий, когда несколько HOC используют одну и ту же опору, возникнут конфликты, и это потребует некоторой продуманной композиции. Главным в этом отношении, вероятно, является опора as, способ динамического изменения того, какой дочерний компонент визуализируется:

import styled from "styled-components";
const Comp = styled.div`
  color: red;
`;
// Now it's a <span> element
<Comp as="span">Hello World!</Comp>

С помощью свойства transient он становится:

import styled from "styled-components";
const Comp = styled.div`
  color: red;
`;
// Now it's a <span> element
<Comp $as="span">Hello World!</Comp>

Обратите внимание, что уделение внимания $as по as, если присутствуют оба, означает, что упаковка другого компонента, который принимает as, будет продолжать работать:

import styled from "styled-components";
const OtherComp = ({ as: asProp, ...props }) => <asProp {...props} onClick={somethingCool} />;
const Comp = styled.div`
  color: red;
`;
// Now it's a <span> element with an onClick handler
// that does something cool
<Comp $as={OtherComp} as="span">Hello World!</Comp>

Будет ли такая ситуация случаться часто? Черт возьми, надеюсь, что нет. Он становится более чем на два уровня глубиной… но это верно и сегодня, и мы улучшаем вариант использования на 90%, что, на мой взгляд, является приемлемым компромиссом.

Итак, окончательный алгоритм таков:

  1. Не пересылайте временные свойства на следующий уровень ($something).
  2. Если указаны как временная, так и обычная версия ($something и something) одного из принятых вами свойств, используйте временную версию и перенаправьте обычную версию вниз.

Существует PR добавить эту возможность в стилизованные компоненты в второстепенном выпуске, с последним изменением, чтобы удалить старый способ фильтрации свойств для следующего основного. Конструктивная обратная связь приветствуется.