🦎

React NativeでもTailwindを使いたい

2020/11/07に公開

React Native の標準スタイリングである StyleSheet も良いのですが、どうも開発スピードが上がらなかったため tailwind-rn を使って Tailwind を導入したので、使い方について紹介。

tailwind-rn を導入

React Native で tailwind を使う場合は、以下のライブラリを使います。(執筆時点のバージョンは 3.x.x

このライブラリは以下の機能を提供しています。

  • tailwindのCSSをReact Nativeのスタイルとして使えるように修正してJSONファイルとして生成するCLIツール
  • アプリケーション内で使用するスタイルを生成する関数

導入手順

とりあえずインストール。

$ npm install tailwind-rn
// or
$ yarn add tailwind-rn

tailwind.config.js を作成する

以下のコマンドで、 tailwind.config.js が生成します。

$ npx tailwindcss init

tailwind.config.jsTailwindの構成についてカスタマイズを定義するファイルです。

tailwind-rn の設定

以下のコマンドで、tailwind.config.js の設定をもとに styles.json が生成されます。

$ npx create-tailwind-rn

styles.json にはTailwindのCSSをReact Nativeでも使えるように変換されたものが入っています。

ここで注意すべき点は、Tailwindには存在するがReact Nativeでは使用できないようなスタイルは事前に生成しないようになっていることです。

何が生成される対象なのかは、以下を確認してください。


次にcreate()にさっき生成したJSONを渡して、tailwindを作ります。exportしてコンポーネントから使えるようにしておきます。

tailwind.ts
import { create } from 'tailwind-rn'
import styles from './styles.json'

const { tailwind } = create(styles)
export { tailwind }

creategetColor というのも返ってくるのですが、今回は説明しないです。(https://github.com/vadimdemedes/tailwind-rn#getcolorcolor)

スタイリング方法

さきほど作成した tailwind 関数を使ってスタイリングをします。

この関数は tailwind('flex-1') といったように、 Tailwindで使うclass名を文字列として渡すことで、React Nativeのstyleで使用できるオブジェクトが返ってきます。

なので、 <View style={tailwind('flex-1')} /> でスタイリングができます。

複数のスタイルをあてるには、スペース区切りで1つの文字列として渡します。
tailwind('flex-1 justify-center items-center')

以下はコンポーネント内で使用した例です。

import React from 'react'
import { View, Text } from 'react-native'
import { tailwind } from './tailwind'

const Component = () => {
    return(
        <View style={tailwind('flex-1 justify-center items-center')}>
            <Text style={tailwind('text-lg')}>中央に大きめの文字が表示されるよ</Text>
        </View>
    )
}

export default Component

カスタマイズ

tailwind.config.js から theme を拡張することでデフォルトで生成されるスタイルを変更したり、追加したりできます。(テーマ拡張はこちらを参考にしてください。)

React NativeのスタイリングはCSSと似ていますが異なります。そのためtailwindにあるすべてのスタイルが使用できるわけではありません。

tailwind-rn では、それを見越して React Native で使えないものは生成しない、あるいは使えるように変換してくれています。
そのためtailwind-rnが標準で生成しないものをtheme拡張で追加しようとしても上手くいかないケースがあります。

そういったケースに対応するには、
custom-styles.jsonなどを作成して、そこに独自のスタイルを追加して、tailwind 関数を作るときに styles.json と合わせて引数に渡します。(最終的にオブジェクトであればいいので必ずしもJSONで定義する必要はありません)

import { create } from 'tailwind-rn'
import styles from './styles.json' // tailwind-rnで生成されたスタイル
import custom from './custom-styles.json' // 独自で追加したいスタイル

const { tailwind, getColor } = create({ ...styles, ...custom })
export { tailwind, getColor }

苦肉の策ですが、この対応方法でおおよそのケースには対応できると思います。

拡張機能

VSCodeを使うことで、tailwindの拡張機能を使うことができます。

https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss

この拡張機能をつかうと、入力の補完ができます。

ですが、候補が出てくる条件がclass=className=と決まっているためtailwind()style=では表示されません。(対応してほしいと、いうIssueはありましたが、tailwind-rnは公式のパッケージではないので対応しない方針のようです。残念。)

もし拡張機能を利用したいなら、頻出するコンポーネントを class あるいは className のpropsでスタイリングできるようにラップするしかなさそうです。

以下は View コンポーネントをラップしたものです。

components/View.tsx
import React from 'react'
import { View } from 'react-native'
import { tailwind } from '~/config/tailwind'

const Component: React.FC<
  React.ComponentProps<typeof View> & {
    className?: string
  } => ({ className, children, style, ...rest }) => (
  <View style={[className ? tailwind(className) : undefined, style]} {...rest}>
    {children}
  </View>
)

export default Component

これでclassNameで受け取れるので入力の補完が効きます。

import React from 'react'
import { Text } from 'react-native'
import View from '~/components/View'

const Component = () => {
    return(
        <View className="flex-1 justify-center items-center">
            <Text>中央に文字が表示されるよ。</Text>
        </View>
    )
}

// styleも使えるので、tailwindにはないスタイルが必要な場合はこんな書き方になる
const WithStyle = () => {
    return(
        <View className="flex-1 justify-center items-center bg-black">
            <View className="bg-white" style={{ height: 50, width: 50 }}>
                <Text>黒い背景の中央に白い正方形と文字が表示されるよ。</Text>
            </View>
        </View>
    )
}

これも苦肉の策ですね…

https://zenn.dev/shon0/articles/2aa72060fb824d

まとめ

Web開発でTailwindを使ったときの体験が忘れられず、React Nativeでもと思って導入してみました。

CSSとの差異や拡張機能の対応など、Webでの開発ほどはTailwindの恩恵にはあずかれていないのが現状ですが、個人的には標準のスタイリングよりはスピード感持って開発できています。

Tailwindを使ったことある人はぜひReact Nativeでも使ってみてください 🙌

Discussion