Closed8
"You and 120% Cleaner React"を見ながら過去のクソコードを成仏させる
この記事を見ながら https://github.com/f-yusei/roten-app ←このクソコードリポジトリを浄化してく
最初は「冥冥たる濁流の useState」を浄化していきます
↓冥冥たる濁流の useStateの説明
これは、React フックスの useState を多用しすぎて、読みづらくなってしまうという問題です。
このアンチパターンの背景には様々な要因が存在しますが、はじめに挙げるのはシンプルに複数の useState をまとめるということを怠ったパターンです。
浄化すべき「冥冥たる濁流のuseState」はリポジトリから見つかりませんでした。
過去の自分やるやん
次は「2. 絶えず自壊するクソでかコンポーネント」です。
これは思い当たる節がありすぎる
ところで、巨大コンポーネントの真の問題は、単に大きいことだけではありません。
本当に厄介なところは、きちんと責務が切れていないところです。
グサッ
クソデカコンポーネント発見、、、
中略を挟みましたが、なんとこのファイルには100行を超えるコンポーネントが複数あります。
return (
<Box maxHeight="100vh">
<HStack>
<OrderButton handleAddToCart={handleAddToCart} />
<Card w={'60vw'} h={'96vh'} p={4} m={2}>
<h1>注文内容</h1>
<Stack bgColor={'gray.50'} h={'88vh'} overflow={'scroll'}>
{cart.map((order, index) =>
order.name === 'ソース(セット)前売り' ? (
<HStack key={order.id}>
<SetCard
order={order}
cart={cart}
handleUpdateOrderCheck={handleUpdateOrderCheck}
/>
<Button
w="12vw"
h="20vh"
borderRadius={10}
m={5}
onClick={() => {
handleDeleteSetMenu(index);
}}
----------------------------------------中略------------------------------------------
handleAddToCart({
id: v4(),
name: 'ソース(セット)前売り',
price: 0,
arranges: {
kind: 'sauce',
sauce: true,
mayo: true,
aosa: true,
katsuo: true,
},
});
handleAddToCart({
id: v4(),
name: 'めんたい(セット)前売り',
price: 0,
arranges: {
kind: 'mentai',
sauce: true,
mentaiMayo: true,
cheese: true,
katsuo: true,
},
});
}}
>
セット
</Button>
</VStack>
);
};
export default ReceptionUI;
ではこのコンポーネントにどんな責務が混在しているか見ていきましょう。
このコンポーネントは露店の注文を受け付ける、受付画面です。そのため本来の責務は、受付機能を支える各コンポーネントを表示させることだと思います。
しかし、現状は
- カートに入っている商品を配列の内容によって表示する
- 合計金額を配列から計算して表示する
という本来負うべきでない責務も背負ってしまっています。
return (
<Box maxHeight="100vh">
<HStack>
<OrderButton handleAddToCart={handleAddToCart} />
<Card w={'60vw'} h={'96vh'} p={4} m={2}>
<h1>注文内容</h1>
<Stack bgColor={'gray.50'} h={'88vh'} overflow={'scroll'}>
{cart.map((order, index) =>
order.name === 'ソース(セット)前売り' ? (
<HStack key={order.id}>
<SetCard
order={order}
cart={cart}
handleUpdateOrderCheck={handleUpdateOrderCheck}
/>
<Button
w="12vw"
h="20vh"
borderRadius={10}
m={5}
onClick={() => {
handleDeleteSetMenu(index);
}}
>
削除
</Button>
</HStack>
) : order.name === 'めんたい(セット)前売り' ? (
<Box key={order.id}></Box>
) : (
<HStack key={order.id}>
<Box width={'40vw'}>
<Grid
templateColumns="repeat(2, 1fr)"
gap={4}
marginLeft={5}
>
<GridItem
colSpan={1}
h="10vh"
w="4vw"
bg="blue.400"
borderRadius={10}
color={'white'}
p={'1.4vw'}
>
単品
</GridItem>
<GridItem colSpan={1}>
<Card key={order.id} w={'35vw'} minH={'8vh'} mt={2}>
<h2>{order.name}</h2>
<HStack>
<CheckboxGroup>
{Object.keys(order.arranges)
.slice(1)
.map((topping, i) => (
<Checkbox
key={i}
defaultChecked={true}
colorScheme="green"
onChange={(e) => {
handleUpdateOrderCheck({
id: order.id,
arrange: topping,
checked: e.target.checked,
});
}}
>
{translateWords(topping)}
</Checkbox>
))}
</CheckboxGroup>
</HStack>
</Card>
</GridItem>
</Grid>
</Box>
<Button
w="12vw"
h="10vh"
m={5}
borderRadius={10}
onClick={() => {
handleDeleteFromCart(order.id);
}}
>
削除
</Button>
</HStack>
),
)}
</Stack>
<HStack>
<h2>合計</h2>
<h2>
{
//注文の合計金額を表示
cart.reduce((sum, order) => sum + order.price, 0)
}
</h2>
<PayDrawer />
</HStack>
</Card>
</HStack>
</Box>
);
このコンポーネントの責務を各部品を表示するだけに修正しました。
なんと30行程度のコンポーネントに🤩
美しいですね
return (
<Box maxHeight="100vh">
<HStack>
<OrderButton handleAddToCart={handleAddToCart} />
<ShowCart
cart={cart}
handleDeleteFromCart={handleDeleteFromCart}
handleUpdateOrderCheck={handleUpdateOrderCheck}
handleDeleteSetMenu={handleDeleteSetMenu}
translateWords={translateWords}
/>
</HStack>
</Box>
);
このスクラップは2024/03/07にクローズされました