私の書いた「ざんねんなコードたち」を公開します…。
誰かの糧にしてもらえれば嬉しいです。
設計の良し悪しは棚に上げておきます。
ただ、「こんな書き方できるよ」の一覧であることをご了承ください。
オブジェクトをくっつけたかったねん…
例えばPropsで受け取ったCSSオブジェクトとコンポーネント側で定義されたCSSオブジェクトをくっつけようとしました。
import { FC, PropsWithChildren } from 'react'
type Props = {
title: string
}
export const Component: FC<
PropsWithChildren<Props>
> = ({ title, children }) => {
// カスタムフックからinitialStylesというCSSオブジェクトが返ってくる
const {
initialStyles,
} = useCustom()
const iconSize = {
width: 20,
height: 20,
}
- const iconStyle = Object.assign({}, initialStyles, iconSize)
+ const iconStyle = { ...initialStyles, ...iconSize }
childrenはもっとシュッとできる
childrenを受け取るコンポーネントを作るときは&
で繋げちゃってました…。
type Props = {
value: string
} & PropsWithChildren
export const Component: FC<Props> = ({value, children}) => {}
PropsWithChildren
でPorps
をラップしてスッキリ。
type Props = {
value: string
}
export const Component: FC<PropsWithChildren<Props>> = ({value, children}) => {}
そのコード見づらない?
tailwindのclassが長く連なった上に、条件分岐を含むと非常に読みにくい…。
- <div className={`flex flex-row items-start gap-4 p-4 ${resolvedBubblePosition === 'left' ? 'justify-end' : 'justify-start'}`}>
tailwind-merge
を使って通常の定義と条件分岐によるclassの定義を分けてみました。
<div
className={twMerge(
'flex flex-row items-start gap-4 p-4',
isLeft ? 'justify-end' : 'justify-start',
)}
>
tailwind-merge
を使うと重複するclassは削除してくれちゃうのでPropsでclassName
を渡すなど動的にスタイルを変更する場合などはtwMerge
、ただの文字列を繋げるだけならtvJoin
を利用するのが良いかと思います!
なので上記の例だとtvJoin
でも問題ないと思います。
コンポーネントのテキストカラー変えたかってん…
textColoe
にはred
みたいにカラー名が入る想定、任意で設定できるOptionalとして定義しました。
tailwind-variants
を利用してスタイルを宣言的に定義している前提で話を進めます。
import { tv } from 'tailwind-variants'
const style = tv({
base: '',
variants: {
color: {
red: 'text-red-500'
}
}
})
type Props = {
index: number
- textColor?: string
+ textColor?: (keyof typeof style.variants.color)
}
一見良さそうなコードですが、textColor
にはred
かundefined
以外の文字列が渡ってきてしまう恐れがあります…。
tailwind-variants
で定義したcolorのkeyを利用することでred
のリテラル型かundefined
しか許容できない型となります。
その数値の羅列はやめとけ
tailwindで実装していた私は下記のように定義してしまいました…。
パッと見た時に規則性がある数値ではないので、使う時に覚えないといけない制約を利用者に与えてしまいます…
type Props = {
- padding?: 1 | 2 | 4 | 6 | 8;
+ padding?: 1 | 2 | 3 | 4 | 5;
+ padding?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
}
- 連番にして中身で呼び出しているclassを変える
- セマンティックな
xs(xsmall)
やlg(large)
のようなキーワードで呼び出す
のような方がわかりやすいかと思います。
まとめ
ここに書いたコードは漏れなく残念なコードだと思っていますが、中には残念に見えるけど致し方ない実装もあると思います…。
「そうなってしまった」のと「あえてそうしている」とは全く別の話なので、チーム内でコミュニケーションをとって対応していけると良いのではないかと思います。