Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 40 additions & 30 deletions code/examples/use-page-state-coupling.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@
<Badge type="info" text="결합도" />
</div>

Avoid creating functions, components, or hooks that handle all tasks of the same type. Managing too many contexts at once makes it difficult to predict the scope of impact when making changes.
쿼리 파라미터, 상태, API 호출과 같은 로직의 종류에 따라서 함수나 컴포넌트, Hook을 나누지 마세요. 한 번에 다루는 맥락의 종류가 많아져서 이해하기 힘들고 수정하기 어려운 코드가 돼요.

## 📝 Code Example
## 📝 코드 예시

The following `usePageState()` hook manages the URL query parameters for the entire page at once.
다음 `usePageState()` Hook은 페이지 전체의 URL 쿼리 파라미터를 한 번에 관리해요.

```typescript
import moment, { Moment } from 'moment';
import { useMemo } from 'react';
import { ArrayParam, DateParam, NumberParam, useQueryParams } from 'use-query-params';

const defaultDateFrom = moment().subtract(3, 'month');
import moment, { Moment } from "moment";
import { useMemo } from "react";
import {
ArrayParam,
DateParam,
NumberParam,
useQueryParams
} from "use-query-params";

const defaultDateFrom = moment().subtract(3, "month");
const defaultDateTo = moment();

export function usePageState() {
Expand All @@ -24,62 +29,67 @@ export function usePageState() {
statementId: NumberParam,
dateFrom: DateParam,
dateTo: DateParam,
statusList: ArrayParam,
statusList: ArrayParam
});

return useMemo(
() => ({
values: {
cardId: query.cardId ?? undefined,
statementId: query.statementId ?? undefined,
dateFrom: query.dateFrom == null ? defaultDateFrom : moment(query.dateFrom),
dateFrom:
query.dateFrom == null ? defaultDateFrom : moment(query.dateFrom),
dateTo: query.dateTo == null ? defaultDateTo : moment(query.dateTo),
statusList: query.statusList as StatementStatusType[] | undefined,
statusList: query.statusList as StatementStatusType[] | undefined
},
controls: {
setCardId: (cardId: number) => setQuery({ cardId }, 'replaceIn'),
setStatementId: (statementId: number) => setQuery({ statementId }, 'replaceIn'),
setDateFrom: (date?: Moment) => setQuery({ dateFrom: date?.toDate() }, 'replaceIn'),
setDateTo: (date?: Moment) => setQuery({ dateTo: date?.toDate() }, 'replaceIn'),
setStatusList: (statusList?: StatementStatusType[]) => setQuery({ statusList }, 'replaceIn'),
},
setCardId: (cardId: number) => setQuery({ cardId }, "replaceIn"),
setStatementId: (statementId: number) =>
setQuery({ statementId }, "replaceIn"),
setDateFrom: (date?: Moment) =>
setQuery({ dateFrom: date?.toDate() }, "replaceIn"),
setDateTo: (date?: Moment) =>
setQuery({ dateTo: date?.toDate() }, "replaceIn"),
setStatusList: (statusList?: StatementStatusType[]) =>
setQuery({ statusList }, "replaceIn")
}
}),
[query, setQuery],
[query, setQuery]
);
}
```

## 👃 Smell the Code
## 👃 코드 냄새 맡아보기

### Coupling
### 결합도

This hook has a broad responsibility: "managing all the query parameters needed for this page." Because of this, components or other hooks within the page may start depending on it, which can rapidly increase the scope of impact when modifying the code.
이 Hook은 "이 페이지에 필요한 모든 쿼리 매개변수를 관리하는 것"이라는 광범위한 책임을 가지고 있어요. 이로 인해 페이지 내의 컴포넌트나 다른 훅들이 이 훅에 의존하게 될 수 있으며, 코드 수정을 할 때 영향 범위가 급격히 확장될 수 있어요.

Over time, this hook may become burdensome to maintain and could evolve into a difficult-to-modify piece of code.
시간이 지나며 이 Hook은 유지 관리가 점점 어려워지고, 수정하기 힘든 코드로 발전할 수 있어요.

::: info

This hook can also be analyzed from a [readability](./use-page-state-readability.md) perspective.
이 Hook은 [가독성](./use-page-state-readability.md) 관점으로도 볼 수 있어요.

:::

## ✏️ Work on Improving
## ✏️ 개선해보기

You can create separate hooks for each query parameter, as shown in the following code.
다음 코드와 같이 각각의 쿼리 파라미터별로 별도의 Hook을 작성할 수 있어요.

```typescript
import { useQueryParam } from 'use-query-params';
import { useQueryParam } from "use-query-params";

export function useCardIdQueryParam() {
const [cardId, _setCardId] = useQueryParam('cardId', NumberParam);
const [cardId, _setCardId] = useQueryParam("cardId", NumberParam);

const setCardId = useCallback((cardId: number) => {
_setCardId({ cardId }, 'replaceIn');
_setCardId({ cardId }, "replaceIn");
}, []);

return [cardId ?? undefined, setCardId] as const;
}
```

Hook이 담당하는 책임을 분리했기 때문에, 수정에 따른 영향이 갈 범위를 좁힐 수 있어요.
그래서 Hook을 수정했을 때 예상하지 못한 영향이 생기는 것을 막을 수 있어요.
Hook이 담당하는 책임을 분리했기 때문에, 수정에 따른 영향이 갈 범위를 좁힐 수 있어요.
그래서 Hook을 수정했을 때 예상하지 못한 영향이 생기는 것을 막을 수 있어요.