다음 맡은 페이지는 검색 페이지이다.
이 페이지에서는 다른 유저를 팔로우 하기 위한 검색 페이지를 의미한다.
검색 필터로 유저명, 목표명 별로 검색을 할 수 있다.
custom hooks를 만들어 검색 내용을 불러오도록 하였으며
검색 필터와 검색 키워드는 useState와 zustand 모두 사용하였음.
그 이유는 의도된 것으로!! 검색 트리거 방식이 검색창에서 enter나 클릭이나 따로 사용자의 이벤트가 들어가야지만 검색이 되게끔 해주도록 하였음.
- 따라서 전역상태가 변할 때마다 refetch 해주도록 하였고 사용자의 이벤트가 입력이 되기 전 렌더링되는 값들은 로컬 상태로 처리하고 입력이 되면 전역상태에 추가되는 것으로 구현하였음.
- 이를 통해 불필요한 데이터 Fetch를 방지하고, 검색이 의도된 경우에만 서버 요청이 이루어지도록 했음.
상태 관리
... 검색 input component
export const SearchInput = () => {
const [localKeyword, setLocalKeyword] = useState('');
const [localFilter, setLocalFilter] = useState('유저명');
const { setSearchKeyword, setSearchFilter } = useSearchStore();
const handleKeyword = (e: ChangeEvent<HTMLInputElement>) => {
setLocalKeyword(e.target.value);
};
const handleKeyPress = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleClick();
}
};
const handleClick = () => {
setSearchKeyword(localKeyword);
setSearchFilter(localFilter);
};
return (
<div className="flex h-48 w-full items-center justify-between rounded-62 bg-white px-16 py-8">
<div className="flex items-center gap-16">
<SearchFilterDropdown
localFilter={localFilter}
setLocalFilter={setLocalFilter}
/>
<Input
className="px-0"
placeholder={PLACEHOLDERS.SEARCH}
value={localKeyword}
onChange={handleKeyword}
onKeyDown={handleKeyPress}
/>
</div>
<FaSearch
className="size-18 cursor-pointer text-custom-gray-100"
onClick={handleClick}
/>
</div>
);
};
데이터 refetching
... 검색 content component
export const SearchContent = () => {
const { searchFilter, searchKeyword } = useSearchStore();
const {
data: searchData,
refetch,
isError,
error,
} = useSearchQuery({
searchField: searchFilter,
keyword: searchKeyword,
});
useEffect(() => {
if (searchKeyword || searchFilter) {
refetch();
}
}, [searchKeyword, searchFilter, refetch]);
return ...
};
AxiosError를 감지하고, 서버에서 반환된 에러 메시지를 사용자에게 명확하게 전달하도록 설계하였으며, 서버 응답이 없는 경우에도 일반적인 오류 메시지를 제공하여 사용자와 개발자 모두가 문제를 빠르게 이해하고 대응할 수 있도록 함.
특히, 검색 결과와 관련된 에러는 사용자 경험에 중요한 영향을 미치기 때문에, 이를 별도로 다루어 신뢰성과 안정성을 높이는 데 중점을 두었음.
...
export const getSearch = async (request: SearchRequest) => {
try {
const response = await axiosInstance.get(API_ENDPOINTS.SEARCH, {
params: request,
});
return response.data;
} catch (error) {
let errorMessage = 'An unknown error occurred.';
if (error instanceof AxiosError) {
if (error.response) {
errorMessage =
error.response.data?.message || 'An unknown error occurred.';
}
}
throw new Error(errorMessage);
}
};
추후 위 함수뿐만 아니라 다른 api 함수들도 status에 따라 구체적인 에러 처리를 확실하게 할 예정임.