Каков предпочтительный способ передачи стилей детям в React & Emotion JS?

Я только начинаю работать с эмоциями после работы с react-jss на несколько лет. Я пытаюсь найти хороший пример передачи (некоторых, возможно, динамических) стилей дочернему компоненту. В react-jss это было довольно тривиально:

// In SomeParent.jsx
... imports etc ...

const useStyles = createUseStyles({
  custom: {
    color: 'blue',
  },
})

export const CustomBody = () => {
  const classes = useStyles()
  return <Body className={classes.custom}>some text</Body>
} 

// In Body.jsx
... imports etc...

const useStyles = createUseStyles({
  body: {
    fontSize: 16,
    color: 'black',
  },
})

const Body = ({ children, className }) => {
  const classes = useStyles()
  return (
    <p
      className={clsx(
        classes.body,
        className,
      )}
    >
      {children}
    </p>
  )
}

По сути, родительские компоненты могут создавать стили и передавать любое количество связанных имен классов через опору (обычно className) дочернему элементу, который затем может использовать их в своей собственной className опоре, комбинируя их с любыми другими стилями, которые необходимы дочернему компоненту.

Эмоции определенно допускают то же самое, но я не могу понять, как они ожидают, что вы это сделаете.

Семантически на дочерней стороне кажется, что стилизованный тегированный литерал шаблона принимает в emotion стилях и передает className опору дочернему элементу, который затем будет работать так же, как в react-jss. Однако я считаю синтаксис styled безумно уродливым и трудным для анализа. Я бы предпочел не заполнять свои родительские файлы потенциально другими дочерними компонентами, обернутыми в styled HOC.

С функциональной точки зрения кажется, что я передаю мою опору из emotion стилей и составляю эти стили в дочернем компоненте, наиболее точно отражая react-jss, но я не могу найти никаких примеров в документации по эмоциям, предполагающих, что это именно то, что они ожидают от вас. Это НЕ ЗАПРЕЩЕНО или что-то в этом роде, просто не выделено. Имеет ли смысл что-то вроде следующего?

// In SomeParent.jsx
... imports etc ...

export const CustomBody = () => {
  return <Body customStyles={css`color: blue`}>some text</Body>
}

// In Body.jsx
... imports etc...

const bodyStyles = css`
  font-size: 16px;
  color: black;
`
const Body = ({ children, customStyles }) => {
  return (
    <p
      css={css`
        ${bodyStyles};
        ${customStyles};
      `}
    >
      {children}
    </p>
  )
}

В документации по композиции ясно указано, что это будет работать (и работает), но не демонстрирует конкретно передача стилей от одного компонента к другому, как это делается в styled документации. Мне так кажется лучше, но меня беспокоит примечание в документации по стилям строк, который указывает на то, что css не возвращает строку класса, а вместо этого возвращает полный объект, который понимается эмоциями на низком уровне. Если этот объект не запомнен emotion (я еще не тестировал это сам), то я получу кучу ненужных повторных рендеров. Я мог бы запоминать строку имени класса, которая включена как часть этого объекта, но я не уверен, насколько это согласовано.

Последнее, что может иметь значение, - это API имен классов. Похоже, это позволило бы мне создать стиль и передать его как строку className дочернему компоненту (так же, как в react-jss и избежать проблемы повторного рендеринга), но, опять же, нужно обернуть КАЖДЫЙ дочерний компонент, который принимает стиль из родительский компонент в ClassNames компоненте, а затем работа с функциями рендеринга кажется безумием.

Я что-то здесь упустил? Принял ли весь мир, что styled и стилизованный компонентный шаблон - это всего лишь путь к этим вещам? Пожалуйста, дайте мне знать, как вы решили эту проблему, или укажите на документацию, которую я просмотрел. Большое спасибо!


person tchryssos    schedule 13.12.2020    source источник


Ответы (1)


На случай, если кто-то позже найдет этот пост, я провел свои собственные тесты, сравнивая производительность каждого из этих методов при создании тегов 1000 p и их раскраске на основе их индекса.

styled был самым эффективным, ClassNames был вторым по производительности (его лучшая производительность обычно соответствовала нижнему пределу производительности styled). Прямая передача тегированного литерала шаблона css была намного хуже, чем любой из двух других, с производительностью в 1,5–2 раза хуже, чем худшая производительность styled.

Условное оформление с помощью передачи реквизита выполняется медленнее, чем статические стили, и использование фильтрации свойств for styled только немного снижает производительность из-за отсутствия фильтрации (вероятно, хороший компромисс для предотвращения ненужных повторных отрисовок, если это потенциальная проблема).

person tchryssos    schedule 20.12.2020
comment
Я могу ошибаться, и, возможно, стоит протестировать, но я думаю, что простая передача объекта непосредственно в опору css может быть более производительной, потому что вам не нужна функция css. Например, просто передача {color: 'black'} в опору css работает. Кроме того, если вы определяете свой css вне своего компонента, это может ускорить процесс до. Как const myStyle = csscolor: black, а затем передать это. Когда вы передаете помеченный шаблон с помощью css`` напрямую, вы фактически вызываете функцию, которая генерирует объект для эмоций, чтобы понять смысл во время рендеринга. В вашем примере я бы сделал css = {[bodyStyles, customStyles]} - person HummingBird24; 07.05.2021
comment
Это позволит избежать вызова css и использования строковой интерполяции. Вот цитата с сайта эмоций для примера работы функции css. css из @ Emotion / React не возвращает вычисленную строку имени класса. Функция возвращает объект, содержащий вычисленное имя и сглаженные стили. Emotion.sh/docs/css-prop (прокрутите вниз до стилей строк). Styled, скорее всего, был более производительным, потому что вы объявили его вне самого компонента. - person HummingBird24; 07.05.2021