(Это будет коротко)

В Gamezop недавно мы начали писать часть редизайна нашего приложения на React Native. Одна из первых возникших проблем заключалась в следующем:

Как эффективно писать наши стили React (Native)?

Проблема

Наше приложение использует собственный шрифт в большинстве представлений, которые у нас есть. Поэтому для каждого визуализированного компонента Text нам пришлось написать несколько правил стиля, например

//HelloTitle.js
const HelloTitle = ({ title }) => (
  <Text style={styles.title}>Hello { title }</Text>
)
const styles = StyleSheet.create({
  title: {
    ...Platform.select({
      ios: {
        fontFamily: 'Gamezop',
      },
      android: {
        fontFamily: 'gamezop',
      }
    })
  }
})

Повторение одного и того же кода повсюду - плохая идея.

Хакерский путь

Одно из предложенных решений заключалось в том, чтобы изолировать повторяющиеся стили в единую глобальную таблицу стилей, подобную глобальным правилам CSS. Запрашивать файл, когда и где это необходимо.

//styles.js
export default StyleSheet.create({
  title: {
    ...Platform.select({
      ios: {
        fontFamily: 'Gamezop',
      },
      android: {
        fontFamily: 'gamezop',
      }
    })
  }
})

Тогда используйте это как

//HelloTitle.js
import Styles from './styles.js'
const HelloTitle = ({ title }) => (
  <Text style={Styles.title}>Hello { title }</Text>
)

Но этот подход, похоже, не соответствовал подходу React, ему не хватало возможности компоновки.

Решение

Компоненты высшего порядка / Пользовательские компоненты

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

//GzpText.js
const GzpText = props => (
  <Text {...props} style={[styles.font, props.style]}>
    {props.children}
  </Text>
)
const styles = StyleSheet.create({
  font: {
    ...Platform.select({
      ios: {
        fontFamily: 'Gamezop',
      },
      android: {
        fontFamily: 'gamezop',
      }
    })
  }
})
export default GzpText

Здесь GzpText обертывает собственный компонент Text, чтобы получить настраиваемый компонент Text, который оборачивает свое дочернее содержимое в компоненты Text с предварительно примененными нашими стилями.

Это замечательно благодаря возможности компоновки, наш компонент HelloTitle можно просто переписать как

//HelloTitle.js
import GzpText from './GzpText'
const HelloTitle = ({ title }) => (
  <GzpText>Hello { title }</GzpText>
)

Некоторые последующие материалы о компонентах более высокого порядка и о том, как они заменяют миксины с помощью композиции.





Обратная связь? Твитни меня!