Next.js と Emotion でいろいろハマった件 3
Next.js で Emotion を使う場合、JSX Pragma がつけられることで Next.js の <Link> コンポーネントが直下の <a> に href をつけてくれなくなるので、その対応をいくつか考えてみました。
また、Next.js や Emotion のバージョンを上げたら起こったことについても書きました。
Version
- TypeScript 4.0.5
- Next.js 10.0.1
- React 17.0.1
- Emotion 10/11
<Link> の直下にある <a> に href が設定されない
公式にしっかり書いてありました。
Note: If you’re using emotion’s JSX pragma feature (
@jsx jsx), you must usepassHrefeven if you use an<a>tag directly.
next/link | Next.js
.babelrc で presets に @emotion/babel-preset-css-prop を追加している場合 @jsx jsx プラグマが有効です。
公式のとおり、 <Link href={url} passHref> としなくてはいけませんでした。
回避策はあるのか
-
@emotion/babel-preset-css-propを使うのをあきらめる-
<Link>の直下に<a>を置くコンポーネントだけを分離し、そのコンポーネントにはプラグマを書かなければpassHrefがなくてもhrefは付与される模様。 -
その代わり
css()を使うすべてのファイルに@jsx jsxを書く必要がある。
-
-
@emotion/coreを使うのをあきらめる-
極論ぽいけれど、
@emotion/coreを使わなければプラグマフラグも必要ないので、@emotion/cssを使う方法がある。 -
css()の結果はstringになり、<someElement css={styles}>ではなく<someElement className={styles}>となる。 -
<Global>が使えない...
-
1.の方法は .tsx に jsx と書くのが大変つらいです。
2.の方法はとある企業のブランドサイトを作った時に実際使用しました。割と普通ですが、<Global> が使えないのでグローバルスタイルだけは普通に .css で読み込む必要がありました。
結局どちらもつらいので、今は @emotion/babel-preset-css-prop を presets に加えた上で、以下のような <Link>をラップするコンポーネントを作って凌いでいます。
type Props = { href: string | URL, as?: string}
const AppLink: React.FC<Props> = props => {
return <Link href={props.href} as={props.as} passHref>
<a>{props.children}<a>
</Link>
}
export default AppLink;
React 17 にしたら @jsx jsx でエラーが出るようになった
Next.js が 10 になったので早速プロジェクトをアップデートし、合わせて React が 17 になったら JSX プラグマで以下のようなエラーが出ました。
/** @jsx jsx */
import { jsx, css } from '@emotion/react'
SyntaxError: pragma and pragmaFrag cannot be set when runtime is automatic.
解決策
jsx ランタイムのオプションが classic から automatic に変わったかららしいです。
公式の通り /** @jsxImportSource @emotion/react */ (Emotion 10 の場合は /** @jsxImportSource @emotion/core */) を使う。
If you are using a zero-config tool with automatic detection of which runtime (classic vs. automatic) should be used and you are already using a React version that has the new JSX runtimes (hence
runtime: 'automatic'being configured automatically for you) such as Create React App 4 then/** @jsx jsx */pragma might not work and you should use/** @jsxImportSource @emotion/react */instead.
Emotion - The css Prop
Emotion 11 になったら @emotion/core がなくなった
Emotion 11 では多くのパッケージの名前が変更されました。
@emotion/core は @emotion/react に変わったそうです。
まとめ
自分が勉強するはやさよりも使用しているパッケージの更新の方がはやいので大変。