タイトル
Reactを、ロジックとstyleを分離した構成にしてみる。(styled-components)
目次
- 開発環境
- 何故この記事を書こうと思ったのか
- ディレクトリの構成とサンプルコード
- 作成したコンポーネントを呼び出してみる&結果
- 作成したコンポーネントのstyleを呼び出したコンポーネントで変更してみる
- 感想
開発環境
"react": "^18.2.0",
"typescript": "^4.9.5",
"styled-components": "^6.1.0"
何故この記事を書こうと思ったのか。
これが正解!というディレクトリ構成がないreactにおいて、
ロジック部分とstyleをstyled-componentsを使って分離する方法を取ってみた。
1コンポーネントの中にロジックとstyleを全て入れてしまうとコードが冗長化してしまう問題もあり、解決策として使用している。
ディレクトリの構成
各コンポーネントごとに、コンポーネント、ディレクトリとindex.tsx, style.tsを作成。
サンプルとして示しやすいので、呼び出し時にh1~h6いずれかの型が必須になるTitleTextを作成した。アトミックデザインでは一番小さな箇所、atoms内。
TitleText(ディレクトリ名)
-index.tsx
-style.ts
まずはindex.tsx
import React, { FC, PropsWithChildren } from "react";
import { STitleText } from "./style";
type Props = {
tag: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
};
const TitleText: FC<Props & PropsWithChildren> = ({
tag,
children,
...other
}) => {
return (
<STitleText as={tag} {...other}>
{children}
</STitleText>
);
};
export default TitleText;
ちょっとした解説と補足
1 asは、propsでタグ名を受け取ると、そのタグ名が適用されるよ(今回は受け取れるタグ名をh1~h6に固定)
2 PropsWithChildrenはあらかじめreactで用意されているchildrenを受け取るための型指定だよ。僕は自分でchildren用のPropsを作成していたけどやっぱり使用頻度が多いものだからデフォルトで用意されていた。
3 呼び出しているコンポーネントに対して、上記のディレクトリ構成内でstyleの変更を行なっているのを明示的にするために「S」を使用して「STitleText」としているよ。
続いてstyle.ts
import { styled } from "styled-components";
export const STitleText = styled.h1`
font-size: 30px;
font-weight: 700;
`
ちょっとした補足と解説。
1 exportを忘れないこと。
2 元はh1だけど、index.tsxでタグ名を必ず必要としているから呼び出し時は変更されるよ
作成したコンポーネントを呼び出してみる&結果
import React, { FC } from "react";
import TitleText from "../../atoms/TitleText";
const TopLayout: FC = () => {
return (
<>
<TitleText tag="h3">結果こんな感じ</TitleText>
</>
);
};
export default TopLayout;
結果
この呼出ではあらかじめ作成しておいたコンポーネントをそのまま使用しているので、TitleTextに対してタグの頭にSは付けていません。
作成したコンポーネントのstyleを呼び出したコンポーネントで変更してみる
呼び出しをする際に、ここではフォントの色を青としたい!!そんな時があるかもしれない。むしろかなりある。
呼び出しコンポーネントも同じディレクトリ構成なので、style.ts内でTitleTextをimport,上書きもしくは追加したいstyleを書き込みましょう
import styled from "styled-components";
import TitleText from "../../atoms/TitleText";
export const STitleText = styled(TitleText)`
color: blue; //追加したいstyle
font-weight: 400; //上書きしたいstyle
`;
先ほどのindex.tsxに作成したSTitleTextを追加する。
import React, { FC } from "react";
import TitleText from "../../atoms/TitleText";
import { STitleText } from "./style";
const TopLayout: FC = () => {
return (
<>
<TitleText tag="h3">結果こんな感じ</TitleText>
<STitleText tag="h4">style上書の結果こんな感じ</STitleText>
</>
);
};
export default TopLayout;
感想
構成などに正解はないので、あくまでも一意見として考えていただけるといいなと思います。
僕はしばらくこれかなぁ。