LoginSignup
31
19

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-12-27

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

31
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
19