Skip to content
Merged
Show file tree
Hide file tree
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
9 changes: 8 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
"@stomp/stompjs": "^7.0.0",
"@tanstack/react-query": "^5.61.3",
"@tanstack/react-query-devtools": "^5.61.3",
"@types/lodash": "^4.17.14",
"@types/react-datepicker": "^6.2.0",
"@types/sockjs-client": "^1.5.4",
"axios": "^1.7.8",
"lodash": "^4.17.21",
"next": "15.0.3",
"react": "^18.3.1",
"react-datepicker": "^7.5.0",
Expand Down
17 changes: 6 additions & 11 deletions src/components/common-layout/FilterBar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import {
CategoryTabs,
SearchSection,
FilterSection,
} from '@/components/common-layout';
import { CategoryTabs, FilterSection } from '@/components/common-layout';
import { BookClubParams } from '@/types/bookclubs';

import SearchInput from '@/components/input/search-input/SearchInput';
interface FilterBarProps {
filters: BookClubParams;
handleFilterChange: (newFilter: Partial<BookClubParams>) => void;
Expand All @@ -14,11 +10,10 @@ function FilterBar({ filters, handleFilterChange }: FilterBarProps) {
return (
<section className="flex w-full flex-col gap-y-3 px-[20px] pt-[20px] md:px-[24px] lg:px-[102px]">
<CategoryTabs filters={filters} onFilterChange={handleFilterChange} />
<SearchSection
searchValue={filters?.searchKeyword || ''}
onSearchChange={(value: string) =>
handleFilterChange({ searchKeyword: value })
}
<SearchInput
value={filters?.searchKeyword || ''}
onChange={(e) => handleFilterChange({ searchKeyword: e.target.value })}
aria-label="책 검색"
/>
<FilterSection onFilterChange={handleFilterChange} />
</section>
Expand Down
33 changes: 26 additions & 7 deletions src/components/input/search-input/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
import { ChangeEvent } from 'react';
import { ChangeEvent, useMemo, useState } from 'react';
import Input from '../Input';
import SearchIcon from '../../../../public/icons/SearchIcon';
import { debounce } from 'lodash';

interface SearchInputProps {
value: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
}

function SearchInput({ value, onChange }: SearchInputProps) {
const [inputValue, setInputValue] = useState(value);

const debouncedOnChange = useMemo(
Copy link
Contributor

Choose a reason for hiding this comment

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

p4: 여기 혹시 useMemo를 사용하신 이유가 있을까요? 이 부분은 useCallback이 어울리지 않을까 해서요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

메모리 누수 방지용 코드에 대해서는 알아봐야 할 것 같아요!

useCallback 말고 useMemo를 사용한 이유는, 처음에는 useCallback으로 햇었는데 lint 에러가 발생하더라구요.

밑에 블로그 보고 해결했습니다.
내용은 "useCallback은 인라인 함수를 기대합니다. debounce나 throttle이 반환하는 함수를 전달하는 것은 적절하지 않습니다. 왜냐하면 ESLint 규칙이 어떤 의존성을 포함해야 하는지 정확히 파악할 수 없기 때문입니다. useMemo를 사용해서 해결해라"

참고 링크

() =>
debounce((value: string) => {
onChange({ target: { value } } as ChangeEvent<HTMLInputElement>);
}, 300),
[onChange],
);

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setInputValue(newValue);
debouncedOnChange(newValue);
};

return (
<Input
value={value}
onChange={onChange}
placeholder={'검색어를 입력해주세요'}
icon={<SearchIcon />}
/>
<div className="bg-white">
<Input
value={inputValue}
onChange={handleChange}
placeholder={'검색어를 입력해주세요'}
icon={<SearchIcon />}
/>
</div>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function ChatBubbleList({
return (
<div className="flex w-full flex-col gap-3 px-5">
{groupedMessages.map((group, groupIndex) => (
<div key={groupIndex} className="flex w-full flex-col gap-3">
<div key={groupIndex} className="flex w-full flex-col gap-2">
<div className="flex items-center justify-center py-1.5">
<div className="rounded-full bg-gray-normal-01 px-3.5 py-1.5 text-sm font-medium text-gray-normal-03">
{group.date}
Expand Down