백엔드에서 search: 인수 받는 게 없을 때 프론트엔드에서만 검색을 해보는 법 !~~~~~~~!!!!!!!!!!
ELK하면 비싸대욤
const [searchedData, setSearchedData] = useState([]);
const onChangeSearchInput = (event) => {
console.log(event.target.value);
const filtered = props.themesAll.fetchThemesAll.filter((themeList) => {
return themeList.title.includes(event.target.value);
});
setSearchedData(filtered);
};
(쓰로틀링이나 디바운싱이 필요할 것 같다.)
1. 이렇게 함수를 만들고
<S.SearchInput
placeholder="테마명을 입력하세요."
onChange={onChangeSearchInput}
/>
{searchedData.map((el: IFetchThemes) => (
<div
key={uuidv4()}
onClick={props.onClickTheme(el)}
style={{ cursor: "pointer" }}
>
<S.Flip>
<S.Card>
<S.Theme src={el.mainImg}>
<S.Rank>
<S.Ranktext>난이도</S.Ranktext>
<S.Star disabled defaultValue={el.rank} />
</S.Rank>
<S.GenreTag>#{el?.genre.name}</S.GenreTag>
</S.Theme>
<S.ThemeBack src="https://res.cloudinary.com/dop5piuwp/image/upload/v1658990939/public/theme/card-back_ef6jjd.png">
<S.ThemeTitle>{el.title}</S.ThemeTitle>
<S.ThemeInfo>
이용인원 ~ {el.peoplelimit}명
<br />
나이제한 {el.agelimit}세
<br />
{el.intro_title}
</S.ThemeInfo>
</S.ThemeBack>
</S.Card>
</S.Flip>
</div>
))}
검색된 데이터를 뿌리는 방식으로 했다.
(이미지는 클라우드 오류로 안 나오는 중)
근데 이렇게 하니까 처음에 아무것도 입력하지 않았을 때 보이는게 없었다.
searchedData의 초기값을 [] 빈 배열로 설정했기 때문이다.
그리고 원래는 searchedData 부분이 props.data?.fetchThemes였는데, 이게 장르별로 분류해서 보여주는 방식이었어서 장르검색이 안됐다.
const [searchedData, setSearchedData] = useState(props.data?.fetchThemes);
const onChangeSearchInput = (event) => {
console.log(event.target.value);
const filtered = props.data?.fetchThemes.filter((themeList) => {
return themeList.title.includes(event.target.value);
});
setSearchedData(filtered);
};
2. 그래서 기본값을 장르로 분류되어 내려온 데이터로 하고, 검색을 하는 데이터 풀도 아예 분류되어온 데이터로 바꿨다.
이번엔 searchedData를 undefined로 인식하는(데이터가 내려오기 전에 map을 돌려버리는) 오류가 발생했다.
이건 뒤에 ?만 붙여주면 된다.
{searchedData?.map((el: IFetchThemes) => (
그렇게하니 빈게...!
{searchedData && searchedData?.map((el: IFetchThemes) => (
이것도 효과는 없었다..!
데이터가 있으면, 맵으로 뿌려줘... 그런 느낌이었는데...
검색창에서 뭐라도 입력하지 않으면 테마들이 나오지 않는다.
위에서 내려온 데이터가 아니라 state를 사용해서 그런 것 같은데 정확한 이유를 모르겠어...
{(searchedData || props.data?.fetchThemes)?.map(
그래서 searchedData가 없을 땐 props.data?.fetchThemes(장르 분류만 되어서 내려온 데이터)를 보여줘! 했더니 뜬다!
잘 되는 줄 알았는데~ 문제!!!!!!
공포에서 검색하다가 검색어 지우고 다른 장르를 누르면 그게 안 뜬다~~~~
장르 버튼을 누를 때 onChangeSearchInput 함수는 작동되지 않고 그럼 당연히 setSearchedData도 작동하지 않기 때문에, searchedData의 값엔 변화가 없는 것...
그럼 버튼을 누를 때, searchedData에 변화를 주어야할 것 같다.
onClickGenre 했을 때 index, selectAll, genre 이렇게 세 개의 스테이트가 변한다. 아, 근데 전체보기를 눌렀을 때도 생각하면 index를 통해 뭔가 하는 게 나을 것 같다. 약간 불편...한데... 장르의 index가 변할 때니까!
장르의 index가 변할 때, setSearchedData(장르 분류만 되어온 데이터)를 하고 검색창 input을 비워주면 될 것 같은데?
아니 그냥 props.data?.fetchThemes가 변할 때 setSearchedData를 하면 될 것 같기도
이렇게 하니 잘됨! input 초기화가 필요하다!
// container
const searchInputRef = useRef<HTMLInputElement>(null);
// presenter
useEffect(() => {
setSearchedData(props.data?.fetchThemes);
props.searchInputRef.current.value = "";
}, [props.data?.fetchThemes]);
겸사겸사 useRef에 타입 지정하는 법도 배웠다! 어렵다 타입스크립트...ㅎㅎㅎ
아무튼 이렇게 직접적으로 Input에 접근할 땐 useRef<HTMLInputElement>(null) 이라고 적어주면 된다!
(props로 넘길 때 타입은 searchInputRef: RefObject<HTMLInputElement>;)
1. 장르별 검색
2. 장르 안에서 검색
3. 장르 안에서 검색 후 다른 장르 눌렀을 때 또 다시 장르별 검색
const getDebounce = _.debounce((data) => {
const filtered = props.data?.fetchThemes.filter((themeList: IFetchThemes) => {
return themeList.title.includes(data);
});
setSearchedData(filtered);
}, 200)
const onChangeSearchInput = (event: ChangeEvent) => {
getDebounce((event.target as HTMLInputElement).value);
};
useEffect(() => {
setSearchedData(props.data?.fetchThemes);
props.searchInputRef.current.value = "";
}, [props.data?.fetchThemes]);
디바운스도 추가했다! 타입도!! !
나 정말 뿌듯해!!!
엉주 매장 검색도 내가 해주기로 했다!
매장검색은 쉽게 끝끝끝
문제 발생~~~
모바일에선 검색창 없애고 캐러셀이 나오게 해뒀는데, 그거랑 상관없이 useEffect는 setSearchData/searchInputRef 비우기를 수행하기 때문에 오류가 났다.
useEffect(() => {
!windowSize && setSearchedData(props.data?.fetchThemes);
if (!windowSize) props.searchInputRef.current.value = "";
}, [props.data?.fetchThemes]);
if(!windowSize)를 붙여주었다.
참고로 windowSize는
const [windowSize, setWindowSize] = useState(false);
const [searchedData, setSearchedData] = useState(props.data?.fetchThemes);
const handleResize = () => {
if (window.innerWidth <= 767) {
setWindowSize(true);
} else {
setWindowSize(false);
}
};
useEffect(() => {
if (window.innerWidth <= 767) {
setWindowSize(true);
}
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [windowSize]);
0주님이 만든 거 갖고 와서 테마에 맞게 쓰고 있다.
참고 블로그! 정말 무한감사...ㅠㅠ
https://sunnyfterrain.github.io/devlog/tips-react-search.html
[React] 검색 기능 구현 하는법
어떠한 페이지 혹은 프로그램에 거의 필수적으로 들어가는 기능이 있다. 바로 검색 기능! 지금은 크게 어려움이 없지만, 처음 공부하던 시절에는 많이 어려웠었고, 필요한 사람이 있을 수 있으
sunnyfterrain.github.io
useRef Type
https://driip.me/7126d5d5-1937-44a8-98ed-f9065a7c35b5
'프론트엔드✏️ > 팀 프로젝트✨' 카테고리의 다른 글
팀 프로젝트 room:in us 회고 (0) | 2022.08.08 |
---|---|
[roominus] 팀 프로젝트 4주차 - 주차별 회고(4) (0) | 2022.08.01 |
JavaScript heap out of memory - 힙 메모리 누수 확인, 디버깅 (0) | 2022.07.28 |
프론트엔드 부트캠프 78일차, 팀 프로젝트(20) 글은 일인당 하나로 제한합니다. (0) | 2022.07.28 |
프론트엔드 부트캠프 77일차, 팀 프로젝트(19) 예약한 자에게만 댓글을 허용하노라 (0) | 2022.07.27 |