エラー内容
Storybook上でEmotionを使ったスタイル指定が効かない問題に直面した。例えば、スタイルを次のようにEmotionのcssを使って書いてみる。
import React from 'react';
import {css} from "@emotion/react";
const myStyle = css`
color: red;
`;
function RedText() {
return (
<div css={myStyle}>'redtext' </div>
)
}
export default RedText;
RedTextは赤い「redtext」という文字を表示してほしい。ところが、これをStorybook上で確認すると、文字は黒のままでスタイルが効いてくれない。
コンソールで確認すると、redtextのdiv要素に次のようなメッセージが出ていた。
<div css="You have tried to stringify object returned from css function. It isn't supposed to be used directly (e.g. as value of the className prop), but rather handed to emotion so it can handle it (e.g. as value of css prop).">
環境
- react 17.0.2
- @storybook/react 6.3.9
- @emotion/react 11.4.1
- @emotion/babel-preset-css-prop 11.2.0
解決方法
-
yarn add @emotion/babel-preset-css-prop
を実行する (2021/11/1追記:Create React Appでejectせずにjsx pragma無しのEmotionを使う(TypeScript編)によれば、babel-preset-css-propよりもbabel-pluginの方が推奨らしい。) -
.storybook/main.js
を次のように編集する
module.exports = {
"stories": [
//自由に編集
],
"addons": [
//自由に編集
],
webpackFinal: (config) => {
config.module.rules.push({
test: /\.(js|jsx)$/,
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
presets: [require.resolve('@emotion/babel-preset-css-prop')],
},
});
return config;
},
};
3. Storybookを起動
解説
Storybook Emotion React
などで検索すると、日本語記事ではReact + TypeScript + emotion の環境に Storybook を導入するがヒットする。これは、webpack.config.jsを.storybookに追加してオーバーライドする解決策。しかし、オーバーライドのためのカスタマイズがされているため採用しづらかった。
また、Githubでは、Emotionのissueであるbabel-preset-css-prop does not work with Storybookと、StorybookのissueであるCan't get emotion's css prop working inside storybookが見つかった。
これらを読むと、.storybook/main.js
にオプションを追加することでwebpack.config.jsを追記せずともwebpackの設定ができるとのこと。ところが、次のような設定では動かなかった(参考)。
module.exports = {
//stories,addonsは省略
babel: async (options) => ({
...options,
presets: [...options.presets, '@emotion/babel-preset-css-prop'],
}),
}
同様に、次のように設定しても動かなかった。(参考)
module.exports = {
//stories,addonsは省略
babel: (config) => {
config.presets.push(require.resolve("@emotion/babel-preset-css-prop"));
return config;
},
}
最終的に、ここを参考にすることで解決した。
module.exports = {
//stories,addonsは省略
webpackFinal: (config) => {
config.module.rules.push({
test: /\.(js|jsx)$/,
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
presets: [require.resolve('@emotion/babel-preset-css-prop')],
},
});
return config;
},
};
一応動くようにはなったが、環境次第なところがありそう。
ここで参考にした2つのissueには他にも多くの対処法が載っているので、また動かなくなったらそれらを試すのがいいと思う。特に、Storybookの方のissueは2021/10/9時点ではまだOpenなので、今後も進展がありそう。