-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ 구현 (#issue 274) #275
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
FAQ 구현 (#issue 274) #275
Changes from 2 commits
6ccdade
2ce5426
382eb4a
823e9b8
939587f
b00e337
bcbca64
29b71ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import { ApiFAQ } from '../models/customerService'; | ||
| import { httpClient } from './http.api'; | ||
|
|
||
| export const getFAQ = async () => { | ||
| try { | ||
| const response = await httpClient.get<ApiFAQ>(`/faq`); | ||
|
|
||
| return response.data.data; | ||
| } catch (e) { | ||
| console.error(e); | ||
| throw e; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import styled from 'styled-components'; | ||
|
|
||
| export const SpinnerWrapper = styled.div` | ||
| height: 60vh; | ||
| `; | ||
|
|
||
| export const Container = styled.section` | ||
| margin-top: 2rem; | ||
| margin-bottom: 5rem; | ||
| width: 100%; | ||
| display: flex; | ||
| justify-content: center; | ||
| `; | ||
|
|
||
| export const Wrapper = styled.div` | ||
| width: 75%; | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 1.5rem; | ||
| `; | ||
|
|
||
| export const ContentBorder = styled.div` | ||
| width: 100%; | ||
| height: 0.5px; | ||
| background: ${({ theme }) => theme.color.placeholder}; | ||
| `; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,35 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Fragment } from 'react/jsx-runtime'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useGetFAQ } from '../../../hooks/useGetFAQ'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import CustomerServiceHeader from '../../../pages/customerService/CustomerServiceHeader'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import Spinner from '../../mypage/Spinner'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import * as S from './FAQ.styled'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import FAQContent from './FAQContent'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function FAQ() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { faqData, isLoading } = useGetFAQ(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!faqData || faqData.length === 0) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isLoading) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <S.SpinnerWrapper> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Spinner /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </S.SpinnerWrapper> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <CustomerServiceHeader title='FAQ' /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <S.Container> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <S.Wrapper> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {faqData.map((list) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Fragment key={list.id}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <FAQContent list={list} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <S.ContentBorder></S.ContentBorder> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Fragment> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </S.Wrapper> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </S.Container> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function FAQ() { | |
| const { faqData, isLoading } = useGetFAQ(); | |
| if (!faqData || faqData.length === 0) return; | |
| if (isLoading) | |
| return ( | |
| <S.SpinnerWrapper> | |
| <Spinner /> | |
| </S.SpinnerWrapper> | |
| ); | |
| return ( | |
| <> | |
| <CustomerServiceHeader title='FAQ' /> | |
| <S.Container> | |
| <S.Wrapper> | |
| {faqData.map((list) => ( | |
| <Fragment key={list.id}> | |
| <FAQContent list={list} /> | |
| <S.ContentBorder></S.ContentBorder> | |
| </Fragment> | |
| ))} | |
| </S.Wrapper> | |
| </S.Container> | |
| </> | |
| ); | |
| } | |
| export default function FAQ() { | |
| const { faqData, isLoading, error } = useGetFAQ(); | |
| if (error) { | |
| return ( | |
| <S.Container> | |
| <S.Wrapper> | |
| <div>FAQ 데이터를 불러오는 중 오류가 발생했습니다. 잠시 후 다시 시도해주세요.</div> | |
| </S.Wrapper> | |
| </S.Container> | |
| ); | |
| } | |
| if (!faqData || faqData.length === 0) return; | |
| if (isLoading) | |
| return ( | |
| <S.SpinnerWrapper> | |
| <Spinner /> | |
| </S.SpinnerWrapper> | |
| ); | |
| return ( | |
| <> | |
| <CustomerServiceHeader title='FAQ' /> | |
| <S.Container> | |
| <S.Wrapper> | |
| {faqData.map((list) => ( | |
| <Fragment key={list.id}> | |
| <FAQContent list={list} /> | |
| <S.ContentBorder></S.ContentBorder> | |
| </Fragment> | |
| ))} | |
| </S.Wrapper> | |
| </S.Container> | |
| </> | |
| ); | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import styled, { css } from 'styled-components'; | ||
|
|
||
| export const ListContainer = styled.div``; | ||
|
|
||
| export const ListWrapper = styled.div` | ||
| display: flex; | ||
| justify-content: space-between; | ||
| align-items: center; | ||
| `; | ||
|
|
||
| export const ListTitle = styled.div` | ||
| font-size: 1.3rem; | ||
| padding-left: 1.5rem; | ||
| font-weight: bold; | ||
| `; | ||
|
|
||
| export const ListPlusButton = styled.button<{ $isOpen: boolean }>` | ||
| transition: transform 500ms ease-in-out; | ||
| ${({ $isOpen }) => | ||
| $isOpen && | ||
| css` | ||
| transform: rotate(45deg); | ||
| `} | ||
| svg { | ||
| width: 1.5rem; | ||
| height: 1.5rem; | ||
| } | ||
| `; | ||
|
|
||
| export const ListContentWrapper = styled.div` | ||
| margin: 0.5rem; | ||
| display: flex; | ||
| gap: 0.5rem; | ||
| `; | ||
|
|
||
| export const ListButtonWrapper = styled.div` | ||
| margin-top: 0.1rem; | ||
|
|
||
| svg { | ||
| width: 1.5rem; | ||
| height: 1.5rem; | ||
| } | ||
| `; | ||
|
|
||
| export const ListContent = styled.div` | ||
| font-size: 1.1rem; | ||
| padding-right: 1.5rem; | ||
| `; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,31 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { ChevronRightIcon, PlusIcon } from '@heroicons/react/24/outline'; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { FAQ } from '../../../models/customerService'; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import * as S from './FAQContent.styled'; | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| interface FAQContentProps { | ||||||||||||||||||||||||||||||||||||||||||||||||
| list: FAQ; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| export default function FAQContent({ list }: FAQContentProps) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const [isFAQContentOpen, setIsFAQContentOpen] = useState<boolean>(false); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||
| <S.ListContainer> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <S.ListWrapper onClick={() => setIsFAQContentOpen((prev) => !prev)}> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <S.ListTitle>{list.title}</S.ListTitle> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <S.ListPlusButton type='button' $isOpen={isFAQContentOpen}> | ||||||||||||||||||||||||||||||||||||||||||||||||
| <PlusIcon /> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </S.ListPlusButton> | ||||||||||||||||||||||||||||||||||||||||||||||||
| </S.ListWrapper> | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
| <S.ListWrapper onClick={() => setIsFAQContentOpen((prev) => !prev)}> | |
| <S.ListTitle>{list.title}</S.ListTitle> | |
| <S.ListPlusButton type='button' $isOpen={isFAQContentOpen}> | |
| <PlusIcon /> | |
| </S.ListPlusButton> | |
| </S.ListWrapper> | |
| <S.ListWrapper | |
| onClick={() => setIsFAQContentOpen((prev) => !prev)} | |
| role="button" | |
| tabIndex={0} | |
| aria-expanded={isFAQContentOpen} | |
| onKeyDown={(e) => { | |
| if (e.key === 'Enter' || e.key === ' ') { | |
| e.preventDefault(); | |
| setIsFAQContentOpen((prev) => !prev); | |
| } | |
| }} | |
| > | |
| <S.ListTitle>{list.title}</S.ListTitle> | |
| <S.ListPlusButton type='button' $isOpen={isFAQContentOpen}> | |
| <PlusIcon /> | |
| </S.ListPlusButton> | |
| </S.ListWrapper> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
button 으로 바꿨잖아
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
import styled from 'styled-components';
export const ListContainer = styled.div`
padding: 2rem 0;
`;
export const ListWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
`;
export const ListTitle = styled.p`
font-size: 1.2rem;
font-weight: 700;
padding: 0 2rem;
`;
export const ListPlusButton = styled.button<{ $isOpen: boolean }>`
display: flex;
justify-content: center;
align-items: center;
margin-right: 2rem;
transform: ${({ $isOpen }) => ($isOpen ? 'rotate(45deg)' : 'none')};
transition: all 500ms;
svg {
width: 1.2rem;
height: 1.2rem;
}
`;
export const ListContentWrapper = styled.div`
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin: 1rem 2rem;
gap: 1rem;
`;
export const ListButtonWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
svg {
width: 1.2rem;
height: 1.2rem;
}
`;
export const ListContent = styled.p`
font-size: 1rem;
padding-right: 2rem;
`;
@YouD0313 네, ListPlusButton은 이미 버튼으로 구현되어 있는 것을 확인했습니다. 하지만 CodeRabbit의 제안은 ListWrapper 컴포넌트(현재 div로 구현됨)에 대한 접근성 개선이었습니다.
토글 기능을 담당하는 div에 role="button", tabIndex={0}, aria-expanded 속성 및 키보드 이벤트(onKeyDown)를 추가하면 키보드만으로도 FAQ를 열고 닫을 수 있어 접근성이 향상됩니다.
🏁 Script executed:
#!/bin/bash
# Check the definition of styled components in FAQContent.styled.ts
cat src/components/customerService/faq/FAQContent.styled.ts
Length of output: 965
@YouD0313 type='button' 속성을 추가하셨지만, 이것만으로는 완전한 접근성 개선이 되지 않습니다. ListPlusButton은 여전히 styled.div로 정의되어 있고, 주요 클릭 영역(ListWrapper)에는 접근성 속성이 없습니다.
CodeRabbit의 제안은 클릭 핸들러가 있는 ListWrapper에 키보드 접근성(onKeyDown)과 ARIA 속성(role, aria-expanded)을 추가하는 것이었습니다. 이는 키보드 사용자와 스크린 리더 사용자에게 필수적인 접근성 기능입니다.
진정한 접근성 개선을 위해서는 styled.div를 styled.button으로 변경하거나, CodeRabbit이 제안한 ARIA 속성과 키보드 이벤트 핸들러를 추가하는 것이 좋습니다.
🧬 Code Graph Analysis Results
Relevant snippet from src/models/customerService.ts (lines 3-7)
export interface FAQ {
id: number;
title: string;
content: string;
}- Defines the
FAQinterface used as the type for thelistprop inFAQContent. - Contains
id,title, andcontentfields.
Relevant snippet from src/components/customerService/faq/FAQ.tsx (lines 8-36)
export default function FAQ() {
const { faqData, isLoading } = useGetFAQ();
if (isLoading) {
return (
<S.SpinnerWrapper>
<Spinner />
</S.SpinnerWrapper>
);
}
if (!faqData || faqData.length === 0) return;
return (
<>
<CustomerServiceHeader title='FAQ' />
<S.Container>
<S.Wrapper>
{faqData.map((list) => (
<S.ToggleWrapper key={list.id}>
<FAQContent list={list} />
<S.ContentBorder></S.ContentBorder>
</S.ToggleWrapper>
))}
</S.Wrapper>
</S.Container>
</>
);
}- Fetches FAQ data and renders a list of
FAQContentcomponents. - Passes each FAQ item as
listprop toFAQContent. - Shows loading spinner while data is loading.
- Returns nothing if no FAQ data is available.
These snippets provide context on the data structure (FAQ interface) and how FAQContent is used within the FAQ list rendering component. This is relevant to understanding the current implementation of FAQContent.tsx and the user comment about changing to a button.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
다시 봐바
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
@YouD0313 죄송합니다. 제가 코드를 자세히 확인하지 않았네요. 다시 살펴본 결과, 이미 접근성을 고려하여 올바르게 구현하셨습니다:
ListWrapper가styled.button으로 구현되어 있음type='button'속성이 추가되어 있음- 컴포넌트 이름도 적절하게
ListPlusIcon으로 변경되어 있음
이미 시맨틱 HTML 버튼 요소를 사용하여 접근성 문제를 해결하셨습니다. 이전 리뷰 코멘트는 오래된 코드를 기반으로 했던 것 같습니다. 수정해 주셔서 감사합니다!
(__/)
(='.'=)
(")_(")
🏁 Script executed:
#!/bin/bash
# Check the current implementation of FAQContent.tsx and styled components
echo "=== FAQContent.tsx ==="
cat src/components/customerService/faq/FAQContent.tsx
echo -e "\n\n=== FAQContent.styled.ts ==="
cat src/components/customerService/faq/FAQContent.styled.ts
Length of output: 2235
@YouD0313 네, 죄송합니다. 코드를 다시 자세히 확인해보니 이미 접근성을 고려하여 올바르게 구현되어 있습니다:
ListWrapper가styled.button으로 정의되어 있음type='button'속성이 이미 추가되어 있음- 버튼 클릭으로 토글 기능이 제대로 구현되어 있음
이미 시맨틱 HTML을 사용하여 접근성을 확보하셨는데, 제가 제대로 확인하지 않고 코멘트를 남겼습니다. 지적해주셔서 감사합니다.
(__/)
(='.'=)
(")_(")
🧬 Code Graph Analysis Results
Relevant snippet from src/models/customerService.ts (lines 3-7)
export interface FAQ {
id: number;
title: string;
content: string;
}- Defines the
FAQinterface used as the type for thelistprop inFAQContent. - Contains
id,title, andcontentfields, all required.
Relevant snippet from src/components/customerService/faq/FAQ.tsx (lines 7-35)
export default function FAQ() {
const { faqData, isLoading } = useGetFAQ();
if (isLoading) {
return (
<S.SpinnerWrapper>
<Spinner />
</S.SpinnerWrapper>
);
}
if (!faqData || faqData.length === 0) return;
return (
<>
<CustomerServiceHeader title='FAQ' />
<S.Container>
<S.Wrapper>
{faqData.map((list) => (
<S.ToggleWrapper key={list.id}>
<FAQContent list={list} />
<S.ContentBorder></S.ContentBorder>
</S.ToggleWrapper>
))}
</S.Wrapper>
</S.Container>
</>
);
}- This component fetches FAQ data using
useGetFAQhook. - Displays a loading spinner while data is loading.
- If no data, returns nothing.
- Maps over
faqDataand rendersFAQContentfor each FAQ item. - Shows how
FAQContentis used and how thelistprop is passed.
These snippets provide context on the data structure (FAQ interface) and usage of the FAQContent component within the FAQ page.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,12 @@ | ||||||||||||||||||||||||||||||||||
| import { useQuery } from '@tanstack/react-query'; | ||||||||||||||||||||||||||||||||||
| import { getFAQ } from '../api/customerService.api'; | ||||||||||||||||||||||||||||||||||
| import { CustomerService } from './queries/keys'; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| export const useGetFAQ = () => { | ||||||||||||||||||||||||||||||||||
| const { data: faqData, isLoading } = useQuery({ | ||||||||||||||||||||||||||||||||||
| queryKey: [CustomerService.faq], | ||||||||||||||||||||||||||||||||||
| queryFn: () => getFAQ(), | ||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return { faqData, isLoading }; | ||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
| export const useGetFAQ = () => { | |
| const { data: faqData, isLoading } = useQuery({ | |
| queryKey: [CustomerService.faq], | |
| queryFn: () => getFAQ(), | |
| }); | |
| return { faqData, isLoading }; | |
| }; | |
| export const useGetFAQ = () => { | |
| const { data: faqData, isLoading, error } = useQuery({ | |
| queryKey: CustomerService.faq, | |
| queryFn: () => getFAQ(), | |
| }); | |
| return { faqData, isLoading, error }; | |
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { ApiCommonType } from './apiCommon'; | ||
|
|
||
| export interface FAQ { | ||
| id: number; | ||
| title: string; | ||
| content: string; | ||
| } | ||
|
|
||
| export interface ApiFAQ extends ApiCommonType { | ||
| data: FAQ[]; | ||
| } |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
데이터 부재 시 처리 로직을 개선하세요.
현재 코드는 데이터가 없을 때 아무것도 반환하지 않습니다(
return;). 이는 컴포넌트에서undefined를 반환하게 되어 잠재적인 렌더링 문제를 일으킬 수 있습니다.📝 Committable suggestion