普通にimportしただけだと動かない
Emotion
というCSSフレームワークを使ってちょっとお試しで実装していました。
package.json
は以下の通りとなっております。
{
"dependencies": {
"@emotion/core": "^10.0.28",
"next": "9.4.4",
"react": "16.13.1",
"react-dom": "16.13.1"
},
"devDependencies": {
"@types/node": "^14.0.22",
"@types/react": "^16.9.43",
"typescript": "^3.9.6"
}
}
スタイルを設定したいページにEmotionをimportしたのですが・・・。
import { Global, css, jsx } from "@emotion/core";
これだけだとスタイルが適応されないので調査いたしました。
どうやら下記のように@jsx jsx
がないとうまいことコンパイルされないようでした。
/** @jsx jsx */
import { Global, css, jsx } from "@emotion/core";
jsx
をコンパイルする際は、Emotionは独自のコンパイラを通す必要があり、/** @jsx jsx */
というJSX Pragmaの記述をしないと動きませんでした。
以下、名著「りあクト! TypeScriptで極める現場のReact開発」から引用
「Emotion はちょっと他のライブラリと違って特殊なことをしているので、使うにあたっていくつか注意事項があるのね。Emotion の文法を使って記述したJSXは通常React.createElement() ではなくEmotion が提供するコンパイラを通す必要があるの。」
「@emotion/core からインポートしてるjsx というのがそのコンパイラね。で、JSX リテラルで書いたコードをそれに渡すためにファイル冒頭で/** @jsx jsx */ の『JSX Pragma』というマジックワードを記述してあげてるの」
「えっ、言われるまで気づきませんでした。そうなんですね」
「さらに、これに起因する注意点が三つあるの。ひとつめは『親コンポーネントでJSX Pragma を使用したら、子のコンポーネントでもJSX Pragma を使わなければならない』こと」
「使わないとどうなるんですか?」
「『ReferenceError: React is not defined』って怒られてコンパイルに失敗するね。場合によっては直上の親コンポーネントにもJSX Pragma が必要なときもある。Presentational Component をインクルードしてContainer Component を作るときとか、それ自体がEmotion を使ってなくてもJSX Pragma を書かないとコンパイルが通らない」
コンパイルエラーとありますが、私の環境ではエラーは出ずに、スタイルが当たらないという状況でした。
実装例
Emotionでは子コンポーネントでもJSX Pragmaの記述が必要ということで、
お試しとして、Indexからヘッダーを呼び出すものを実装してみました。
↓こんな感じです。
src
│
└─pages
index.tsx
header.tsx
/** @jsx jsx */
import { Global, css, jsx } from "@emotion/core";
const globalCss = css`
* {
margin: 0;
padding: 0;
}
`;
const styles = {
titleBase: css`
height: 168px;
width: 100%;
`,
title: css`
height: 168px;
width: 100%;
font-family: Roboto;
font-size: 64px;
color: #ffffff;
background: #2f80ed;
`,
};
interface Props {
title: string;
}
const Header = (props: Props) => {
return (
<>
<Global styles={globalCss} />
<div css={styles.titleBase}>
<h1 css={styles.title}>{props.title}</h1>
</div>
</>
);
};
export default Header;
import Header from "./header";
/** @jsx jsx */
import { css, jsx } from "@emotion/core";
const styles = {
content: css`
height: 100%;
width: 100%;
font-size: 64px;
`,
};
export default function Index() {
return (
<>
<Header title="タイトル" />
<div css={styles.content}>Content</div>
</>
);
}
Emotionをjsxで使いたい場合、JSX Pragmaを忘れずにつける必要がありました。気を付けたいですね