CSS in JS系のライブラリの中では、emotionが一番好きです。
今まで、@emotion/core
はJSX Pragma (/** @jsx jsx */
)を書くのが必須と思っており、Reactに載せてるのにわざわざemotion
の方を使っていました。
しかし、@emotion/babel-preset-css-prop
を使えば、💩みたいなJSX Pragmaをいちいち書く必要なんてありませんでした。ほんと嬉しいので、共有しておこうと思い記事化しただけの記事です。
Before
そもそもTypesScriptだからtsx
なのに、@jsx
と書かなければならないのは 🤮です。
/** @jsx jsx */
import React from 'react';
import { jsx } from '@emotion/core';
const Greeting: React.FunctionComponent = () => {
return(
<p css={{
backgroundColor: 'hotpink'
}}>
Hello Statham
</p>
)
}
After
@emotion/babel-preset-css-prop
を追加 (yarn add --dev @emotion/babel-preset-css-prop
) して、babel
のconfig or webpackのbabel-loader
のconfigにpresetsを追加するだけです。
自分のwebpack.config.jsのbabel-loader
の部分はこんな感じ。
{
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: true,
babelrc: false,
sourceType: 'unambiguous',
presets: [
['@babel/preset-env', { useBuiltIns: 'usage', corejs: 3 }],
'@babel/preset-typescript',
'@babel/preset-react',
'@emotion/babel-preset-css-prop',
],
plugins: ['@babel/plugin-proposal-class-properties'],
},
},
],
},
そうすれば、もう何もimport
する必要はない。(@emotion/core
とか長いので、それを書く必要すらないのも素晴らしい。)
import React from 'react';
const Greeting: React.FunctionComponent = () => {
return(
<p css={{
backgroundColor: 'hotpink'
}}>
Hello Statham
</p>
)
}
css
に対する型定義も忘れずに
なんの定義もしないまま、ただHTMLタグにcss
だけ生やそうとすると、もちろんエラーが出る。
Property 'css' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>'.ts(2322)
この場合、どこでもいい (自分はglobal.d.ts
にした) ので、/// <reference types="@emotion/core"/>
この一文を追加しておく。
ref: https://github.com/emotion-js/emotion/issues/693#issuecomment-448088489
以上でDONE。さよならJSX Pragma。
何故今まで気がつかなかったのか。。。
そもそも、自分が使い始めた当初である昨年の秋冬にはギリギリ存在しなかった。
ただそれより、Introductionのページにもっと大きく注意を引く感じで記載して欲しかった。。
まぁこれで、来年も快適なemotion lifeを送れそうです。
追記: css
propsを使用している場合に、React component 間で子要素に css props を渡す方法
ドキュメント曰く、コンポーネントに渡されたcss
props はclassName
props にコンバートされるようで、className
props は css
props の内容より優先度高く適用されるようです。
つまり、
type Props = {
className?: string
}
const Children: React.FunctionComponent<Props> = ({ className }) => {
return (
<div className={className} css={{ color: 'blue' }}>
Children
</div>
);
};
const Parent: React.FunctionComponent = () => {
return (
<Children css={{ color: 'red' }} />
);
};
このようにすると、Children
の文字色は赤になります。
Props
の型定義にcss
が必要ないのは、上述の通り global に css
を定義したからです。
うーん、素晴らしい!使いやすいですね。
ただ少しあれなのは、css
はグローバルに定義されているため、どんなコンポーネントにも付与できますが、そのスタイルが適用されるかは、コンポーネントの実装にclassName
props を渡す実装が含まれているかに寄るところで、辛いです。😥