반응형
15. AutoComplete 기능 생성하기
검색을 했을때 그에 관련된 검색어를 가져올 수 있게 서버에서 포켓몬 이름을 전달해주면 좋지만 그런 API는 없다. 따라서 이 기능을 구현하려면 프론트엔드에서 먼저 모든 포켓몬의 데이터를 가지고 있어야 한다.
현재는 포켓몬 데이터 limit을 20으로 설정하고있기 때문에 소스 코드의 수정이 필요하다.
refactoring
function App() { // 모든 포켓몬 데이터를 가지고 있는 State const [allPokemons, setAllPokemons] = useState([]); // 실제로 리스트로 보여주는 포켓몬 데이터를 가지고 있는 State const [displayedPokemons, setDisplayedPokemons] = useState([]); // 한번에 보여주는 포켓몬 수 const limitNum = 20; const url = `https://pokeapi.co/api/v2/pokemon/?limit=1008&offset=0`; const [searchTerm, setSearchTerm] = useState(""); const debouncedSearchTerm = useDebounce(searchTerm, 500); useEffect(() => { fetchPokeData(); }, []); const filterDisplayedPokemonData = (allPokemonsData, displayedPokemons = []) => { const limit = displayedPokemons.length + limitNum; // 모든 포켓몬 데이터에서 limitNum만큼 더 가져오기 const array = allPokemonsData.filter((_, index) => index + 1 <= limit); // 20n filter return array; } const fetchPokeData = async () => { try { const response = await axios.get(url); setAllPokemons(response.data.results); setDisplayedPokemons(filterDisplayedPokemonData(response.data.results)); } catch (error) { console.error(error) } } return ( ... <section className="pt-6 flex flex-col justify-content items-center overflow-auto z-0"> <div className="flex flex-row flex-wrap gap-[16px] items-center justify-center px-2 max-w-4xl "> {displayedPokemons.length > 0 ? ( displayedPokemons.map(({ url, name }, index) => ( <PokeCard key={index} url={url} name={name} /> )) ) : ( <h2 className="font-medium text-lg text-slate-900 mb-1"> 포켓몬이 없습니다. </h2> )} </div> </section> {allPokemons.length > displayedPokemons.length && displayedPokemons.length !== 1 && ( <div className="text-center"> <button onClick={() => setDisplayedPokemons( filterDisplayedPokemonData(allPokemons, displayedPokemons) ) } className="bg-slate-800 px-6 py-2 my-4 text-base rounded-lg font-bold text-white" > 더 보기 </button> </div> )} </article> ); }
16. AutoComplete 컴포넌트 생성하기
AutoComplete.jsx
검색영역 컴포넌트로 가져오기
const AutoComplete = ({ allPokemons, setDisplayedPokemons }) => { const [searchTerm, setSearchTerm] = useState(""); const debouncedSearchTerm = useDebounce(searchTerm, 500); const filterNames = (input) => { const value = input.toLowerCase(); console.log(allPokemons); return value ? allPokemons.filter((e) => e?.name.includes(value)) : []; }; const handleSubmit = (e) => { e.preventDefault(); let text = searchTerm.trim(); setDisplayedPokemons(filterNames(text)); setSearchTerm(""); }; return ( <div className="relative z-50"> <form onSubmit={handleSubmit} className="relative flex justify-center items-center w-[20.5rem] h-6 rounded-lg m-auto" > <input type="text" onChange={(e) => setSearchTerm(e.target.value)} value={searchTerm} className="text-xs w-[20.5rem] h-6 px-2 py-1 bg-[hsl(214,13%,47%)] rounded-lg text-gray-300 text-center" /> <button type="submit" className="text-xs bg-slate-900 text-slate-300 w-[2.5rem] h-6 px-2 py-1 rounded-r-lg text-center absolute right-0 hover:bg-slate-700" > 검색 </button> </form> </div> ); };
검색시 autocomplete
const checkEqualName = (input) => { const filteredArray = filterNames(input); // 검색어 일치하는게 있으면 없애기 return filteredArray[0]?.name === input ? [] : filteredArray; // 배열첫번째거에 이름이 있으면 빈배열 }
UI
{checkEqualName(searchTerm).length > 0 && ( <div className={`w-full flex bottom-0 h-0 flex-col absolute justify-center items-center translate-y-2`} > <div className={`w-0 h-0 bottom-0 border-x-transparent border-x-8 border-b-[8px] border-gray-700 -translate-y-1/2`}> </div> <ul className={`w-40 max-h-[134px] py-1 bg-gray-700 rounded-lg absolute top-0 overflow-auto scrollbar-none`} > {checkEqualName(searchTerm).map((e, i) => ( <li key={`button-${i}`}> <button onClick={() => setSearchTerm(e.name)} className={ `text-base w-full hover:bg-gray-600 p-[2px] text-gray-100` } > {e.name} </button> </li> ))} </ul> </div> )}
tailwind scrollbar사용하기
설치: npm install -D tailwind-scrollbar
등록: tailwind.config.cjs에서plugins: [require('tailwind-scrollbar')],
추가
반응형
'Frontend > React' 카테고리의 다른 글
[React] 포켓몬도감 만들기5 (1) | 2023.12.08 |
---|---|
[React] 포켓몬도감 만들기4 (0) | 2023.12.08 |
[React] 포켓몬도감 만들기2 (0) | 2023.12.08 |
[React] 포켓몬도감 만들기1 (1) | 2023.12.08 |
[emotion] 이모션을 styled-component처럼 사용하기(@emotion/styled) (0) | 2023.09.05 |