styled-componentsをTypescriptで使う上でのTips
はじめに
今回はTypescript + React
でstyled-components
を使う場合のTipsを紹介します。
style
プロパティで直接記載するよりもスタイルの管理がしやすい+使い回しやすいといったメリットがあるのでおすすめです。
※普段はReact Native
を扱っていますが、styled-components
に着目した場合の使用感はほぼ同じといっていいので、サンプルコードはReact
のものになります。
styled-components
とは
そもそもstyled-components
は所謂CSS in JS
ライブラリの一種になります。
名前が表す通り、JS
もしくはTS
のコード中にCSS
を記載していく形になります。
デフォルトのReact
プロジェクトだと、コンポーネント自体はJS
やTS
で記載しますが、スタイルはCSS
ファイルのまとまっています。
それらを 1ファイルにまとめる ことができるのが最大のメリットです。
スタイルはテンプレートリテラルで記載することを基本とし、作成したコンポーネントのスタイルを継承したり、さらに拡張したりすることができます。
上記の内容だけではピンとこない方も多いと思うので、実際に使ってみましょう。
実際に使ってみる
以下、実際に動くサンプルを作ってみる例です。
React + Typescript
のプロジェクトは既に作成してあるものとします。
インストール
yarn add styled-components
yarn add --dev @types/styled-components
基本的な書き方
以下にstyled-components
を使って、ラベルの色を赤く、文字を太くした場合のボタンコンポーネントの例を示します。
import React from "react";
import styled from "styled-components";
// 基本的なstyled-componentsの使い方
const CustomButton = styled.button`
color: red;
font-weight: bold;
`;
このCustomButton
の使い方は、通常のbutton
コンポーネントと同じです。
<CustomButton>ほげほげ</CustomButton>
これはbutton
コンポーネントに下記のようにstyle
を指定したのと同じになります。
<button style={{color: "red", fontWeight: "bold"}}>ほげほげ</button>
見てわかる通り、よりCSSに近い記法になっているかと思います。
このスタイルを指定している箇所は 「テンプレートリテラル」 と呼ばれています。
対して、上記の<button>
の例のようなスタイルの指定の記法を 「オブジェクトリテラル」 と呼びます。
styled-components
を使用することで、デフォルトのコンポーネントをそのままrender
するケースが減少するかと思います。
独自定義したコンポーネントにも対応している
では、自作のコンポーネントやライブラリからimport
してきたコンポーネントにもstyled-components
でスタイルを適用したい場合はどうでしょうか。
styled-components
ではそういったコンポーネントもサポートしています。
以下に例を示します。
Hoge
という<p>
をラップしたシンプルなコンポーネントがあったとします。
import React from 'react';
const Hoge: React.VFC = (props) => <p {...props}>Original Component</p>;
このHoge
に対してstyled-components
でスタイルを指定したい場合は下記のように記載します。
import React from "react";
import styled from "styled-components";
const Hoge: React.VFC = (props) => <p {...props}>Original Component</p>;
// Hogeに対してスタイルを適用する
const CustomHoge = styled(Hoge)`
color: purple;
`
外部のライブラリからimport
してきたコンポーネントも同様に扱う事ができます。
プロパティによって変動するスタイルの定義
button
コンポーネントでよくあるのが「disabled
だけスタイルを変更したい」といったケースです。
styled-components
では、コンポーネントに渡されるプロパティの値によってスタイルを制御することも可能です。
その場合は以下のように記載します。
import React from "react";
import styled from "styled-components";
// props.disabledでcolorを変化させる
const CustomButton = styled.button`
color: ${(props: React.ButtonHTMLAttributes<HTMLButtonElement>) => props.disabled? 'red': 'blue' };
font-weight: bold;
`;
これでbutton
がdisabled
の状態の時のみ文字色が赤くなり、それ以外の時は青くなります。
ここで使用しているprops
はbutton
のprops
の型と同じになります。
従って、props
はReact.ButtonHTMLAttributes<HTMLButtonElement>
型となります。
プロパティをカスタムする
上記のbutton
のdisabled
のようなプロパティではなく、独自で定義したプロパティを使いたい場合があるかと思います。
その場合はジェネリクスとして型を渡すことで対応することができます。
下記のように記載します。
import React from "react";
import styled from "styled-components";
// 独自定義のプロパティ
type CustomProps = {
hoge?: boolean;
};
const CustomButton = styled.button<CustomProps>`
color: ${(props) => props?.hoge? 'red': 'blue'};
`
これでCustomButton
にhoge
というプロパティを渡すことで文字色を制御できるようになりました。
こういったケースの場合、カスタムしたプロパティは大概必須ではないと思います。
その場合はコンポーネントのdefaultProps
を指定して、初期値を決めておきましょう。
import React from "react";
import styled from "styled-components";
// 独自定義のプロパティ
type CustomProps = {
hoge?: boolean;
};
const CustomButton = styled.button<CustomProps>`
color: ${(props) => props?.hoge? 'red': 'blue'};
`
// hogeの初期値をfalseにしておく
CustomButton.defaultProps = {
hoge: false;
}
ここまでをまとめたサンプル
ここまでの内容をまとめたサンプルコードを以下に記します。
import React, { useCallback, useMemo, useState } from "react";
import styled from "styled-components";
// 基本的なstyled-componentsの使い方
const CustomButton = styled.button`
color: red;
font-weight: bold;
`;
// Propsの値によってスタイルを制御する例
// ここでは<p>のプロパティの1つであるchildrenを使っている
const CustomParagraph1 = styled.p`
color: ${(props) =>
props.children === "someFlg is True" ? "green" : "blue"};
`;
// 独自定義のプロパティ
type CustomProps = {
hoge?: boolean;
};
// 継承 + 拡張したプロパティを使う例
const CustomParagraph2 = styled(CustomParagraph1)<CustomProps>`
color: ${(props) => (props.hoge ? "pink" : "red")};
`;
// プロパティの初期値を設定することもできる
CustomParagraph2.defaultProps = {
hoge: false
};
const App: React.FC = () => {
const [someFlg, setSomeFlg] = useState(false);
const reverseFlg = useCallback(() => {
setSomeFlg((flg) => !flg);
}, []);
const label = useMemo(() => {
return someFlg ? "someFlg is True" : "someFlg is False";
}, [someFlg]);
return (
<div className="App">
<CustomButton onClick={reverseFlg}>フラグ書き換え</CustomButton>
<CustomParagraph1>{label}</CustomParagraph1>
<CustomParagraph2 hoge={someFlg}>CustomType Sample</CustomParagraph2>
</div>
);
};
export default App;
画面上のボタンを押下することで、state
の値が変化し、それに伴ってstyled-components
から動的にスタイルが反映されるのが分かるかと思います。
まとめ
今回はReact + Typescript
の環境下でstyled-components
を扱っていくTips的な内容をまとめました。
オブジェクトリテラルの記法に慣れていると、最初は取っ付きづらい印象を受けますが、アプリの規模が大きくなるにつれてスタイルの管理がしやすくなるかと思います。
今回の内容が参考になりましたら幸いです。
Discussion