Help us understand the problem. What is going on with this article?

@emotion/core は @jsx jsx を書かなくても使える

CSS in JS系のライブラリの中では、emotionが一番好きです。

今まで、@emotion/coreはJSX Pragma (/** @jsx jsx */)を書くのが必須と思っており、Reactに載せてるのにわざわざemotionの方を使っていました。

しかし、@emotion/babel-preset-css-propを使えば、💩みたいなJSX Pragmaをいちいち書く必要なんてありませんでした。ほんと嬉しいので、共有しておこうと思い記事化しただけの記事です。

Before

そもそもTypesScriptだからtsxなのに、@jsxと書かなければならないのは 🤮です。

Greeting.tsx
/** @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の部分はこんな感じ。

webpack.config.js
{
  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とか長いので、それを書く必要すらないのも素晴らしい。)

Greeting.tsx
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 を渡す実装が含まれているかに寄るところで、辛いです。😥

Statham
JS (Jason Statham)が好きです。あとは、JS (JavaScript)とか、Solidityとか。ReactとTSは大好きです。最近はGoを少し触りましたが嫌になって、Rustに出会い、今は幸せです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away