Эталонный шаблон для неструктурированной фильтрации пропуска в компонентах более высокого порядка.
Если вы используете библиотеку компонентов более высокого порядка (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%, что, на мой взгляд, является приемлемым компромиссом.
Итак, окончательный алгоритм таков:
- Не пересылайте временные свойства на следующий уровень (
$something
). - Если указаны как временная, так и обычная версия (
$something
иsomething
) одного из принятых вами свойств, используйте временную версию и перенаправьте обычную версию вниз.
Существует PR добавить эту возможность в стилизованные компоненты в второстепенном выпуске, с последним изменением, чтобы удалить старый способ фильтрации свойств для следующего основного. Конструктивная обратная связь приветствуется.