Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: 메인 페이지 개발 #148

Merged
merged 36 commits into from
Oct 4, 2023
Merged

Conversation

cham0287
Copy link
Collaborator

📌 이슈 링크


📖 작업 배경

  • 로그인 기능까지 구현한 뒤에 merge 하려 했으나, 로그인 기능 구현에 생각보다 시간이 많이 걸리고 PR도 너무 커질 것 같아
    나누어서 PR을 올립니다.

🛠️ 구현 내용

메인 페이지

  • pagination 기능 구현 및 popular tags 필터링 기능 구현: zustand로 전역 상태를 사용하여 관리하였습니다.

💡 참고사항

  • atomic design pattern의 atoms만 가져다 쓰는 느낌으로, 최소 단위에서 재사용이 가능해 보이는 컴포넌트들은
    components 하위 atoms / buttons 폴더에 따로 분리해두었습니다.

  • getArticles 함수에서, article을 get하기 위한 params들을 요청에 query params로 넣어주어야 하는데,
    const formedParams = Object.entries(params)
    .map(([key, value]) => value && ${key}=${value}&)
    .join("");
    이런 식으로 문자열 처리를 하여 url 뒤에 바로 추가해서 넣어줬는데 더 나은 방법이 있을 것 같은데 아직 찾지 못했습니다.

  • 메인 페이지에 Tabs를 구현할 때, 로그인 된 상태에서는 Global Feeds 좌측에 My Feeds가 추가되고,
    popular tag를 클릭했을 시에는 우측에 # tag tab이 추가되는데,

    Tab이 더 추가될 것을 고려하여 3개의 고정된 탭을 조건부로 렌더링해주는 Tabs 컴포넌트가 아니라
    prop으로 Tab의 정보를 담은 배열을 받아서 map으로 모두 렌더링해주는 Tabs 컴포넌트를 만들었는데

    // Tabs.tsx 구현부

      {tabs.map((tab) => tab && )}
    ; // Tabs.tsx 사용 부분

    이런 식으로 undefined일 시에는 rendering 되지 않도록 구현했는데 이 방법도 깔끔하지 못하다는 느낌이 들었지만
    다른 더 좋은 구현 방법을 아직 찾지 못했습니다.


🖼️ 스크린샷


Comment on lines 22 to 31
type ArticlesState = {
articlesParams: ArticleQueryParams;
};

type ArticlesStoreActions = {
setSelectedTag: (tag: string) => void;
resetSelectedTag: () => void;
setCurrentPage: (selectedPage: number) => void;
resetCurrentPage: () => void;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type/interface는 가급적 상단에 위치시키는 것을 추천드립니다! 읽다가 혼동이 올 수 있거든요💪

src/stores/useStore.ts Show resolved Hide resolved
Comment on lines 4 to 7
interface PopularTagBtnProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode;
selected: boolean;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ButtonHTMLAttributes이나 HTMLButtonElement에 children 속성이 있어서 별도 명시해주지 않으셔도 될 거 같아요!

Comment on lines +10 to +11
{...props}
className="border border-primary rounded-md text-primary text-sm p-1 bg-none hover:text-white hover:bg-primary"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 순서라면 외부에서 className을 주입해도 아무런 영향이 없겠네요! 의도하신 걸까요?

Comment on lines 9 to 10
};
export default Tag;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한 칸 띄워주면 어떨까요!
원시형 데이터만 받는 컴포넌트는 memo도 추천드립니다 🤗

Comment on lines 20 to 30
const renderPaginationButtons = () => {
const pageBtns = [];
for (let i = 1; i <= Math.ceil(count / 10); i++) {
pageBtns.push(
<PageBtn key={i} onClick={() => handlePageClick(i)} isActive={i === currentPage}>
{i}
</PageBtn>,
);
}
return pageBtns;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Array 구문을 활용하면 좋을 것 같아요.

  const PaginationButtons = () => {
    return [...Array(Math.ceil(count / 10))].map((_, index) => (
      <PageBtn key={index} onClick={() => handlePageClick(index)} isActive={index === currentPage}>
        {index}
      </PageBtn>
    ));
  };

src/components/Articles.tsx Outdated Show resolved Hide resolved
Comment on lines +15 to +21
const { isLoading, data: articleResponse } = useQuery(
["/api/articles", articlesParams],
() => getArticles(articlesParams),
{
refetchOnWindowFocus: false,
},
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

훅으로 분리해두면 어떨까요?

src/components/ArticleCard.tsx Outdated Show resolved Hide resolved
Comment on lines +15 to +19
const {
user: { token },
} = await fetchRegisterUser(registerInput);
localStorage.setItem("token", token);
router.push("/");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러 역할이 뭉쳐 있는 것 같아요. 훅으로 분리해보면 어떨까요?

@cham0287 cham0287 merged commit 4f02927 into pagers-org:team4/cham0287 Oct 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants