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 usepassHref
even 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
に変わったそうです。
まとめ
自分が勉強するはやさよりも使用しているパッケージの更新の方がはやいので大変。