프로젝트 메인페이지에서
필요한 정보들을 api - axios get 해서 가져오고,
그 정보들을 하나의 객체로 묶어, 배열 state (useState) 에 하나씩 담고 map으로 돌리면서 출력했다.
<Thumbnail>은 컴포넌트 !
그 외에도 input에 부여하는 onKeyDown 속성 등을 배웠다.
이번에는 trim() 메서드를 사용해 유효성 검사도 추가 !
(다른 분들이 쓰신 코드도 있음 /스타일컴포넌트 부분은 생략)
import { useEffect, useState } from 'react';
import styled from 'styled-components';
import HeaderSlider from '../sliders/HeaderSlider';
import { useMostPopularVideos } from '../../hooks/useMostPopularChannel';
import { getMostChannelInfo, getMostPopularThumbnails } from '../../api/dataApi';
import Thumbnail from '../main/Thumbnail';
import { useNavigate } from 'react-router-dom';
import BodySlider from '../sliders/BodySlider';
export default function Main() {
const navigate = useNavigate();
const [channelInfos, setChannelInfos] = useState([]);
const { data: videos, isLoading, isError } = useMostPopularVideos();
const [searchTerm, setSearchTerm] = useState('');
const searchIconSrc = 'https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/icon/search.png';
const keyWords = ['먹방', '여행', '생활', '운동', '뷰티', '패션'];
const order = ['1st', '2nd', '3rd', '4th', '5th'];
useEffect(() => {
const getThumbnails = async () => {
if (videos) {
const newChannelInfos = [];
for (const video of videos.slice(0, 5)) {
const channelTitle = video.snippet.channelTitle;
const channelThumbnail = (await getMostPopularThumbnails(video.snippet.channelId)).high.url;
const channelCustomUrl = await getMostChannelInfo(video.snippet.channelId);
const channelUrl = `https://www.youtube.com/${channelCustomUrl}`;
const channelInfo = { channelTitle, channelThumbnail, channelUrl };
// console.log(channelThumbnail);
newChannelInfos.push(channelInfo);
}
setChannelInfos(newChannelInfos);
}
};
getThumbnails();
}, [videos]);
const handleSearchInputChange = (e) => {
setSearchTerm(e.target.value);
};
// Enter 키를 눌러 검색 (=> 리스트페이지로 이동)
const handleSearchEnter = (e) => {
if (e.key === 'Enter') {
if (!searchTerm.trim()) {
return alert('검색어를 입력해주세요.');
}
navigate(`/list/${searchTerm}`);
}
};
// 검색아이콘 눌러 검색 (=> 리스트페이지로 이동)
const handleSearchClick = () => {
if (!searchTerm.trim()) {
return alert('검색어를 입력해주세요.');
}
navigate(`/list/${searchTerm}`);
};
const handleKeyWordClick = (keyword) => {
navigate(`/list/${keyword}`);
};
const handleChannelClick = (channelUrl) => {
window.open(channelUrl, '_blank');
};
if (isLoading) return <div>..Loading</div>;
if (isError) return <div>{isError.message}</div>;
return (
<MainWrap>
<HeaderSlider />
<MainSearch>
<SearchInputBox>
<input
id="search-input"
type="search"
placeholder="원하는 주제를 검색해보세요 !"
value={searchTerm}
onChange={handleSearchInputChange}
onKeyDown={handleSearchEnter}
/>
<img src={searchIconSrc} onClick={handleSearchClick} />
</SearchInputBox>
<SearchKeyWord>
{keyWords.map((keyword) => {
return (
<KeywordText key={keyword} onClick={() => handleKeyWordClick(keyword)}>
#{keyword}
</KeywordText>
);
})}
</SearchKeyWord>
</MainSearch>
<BodySlider />
<MainBest>
<MainBestTitle>
<h3>Best YouTuber</h3>
<p>이달의 인기 유튜버</p>
</MainBestTitle>
<MainBestContWrap>
{channelInfos.map((channelInfo, index) => (
<BestYoutuber>
<p>{order[index]}</p>
<Thumbnail
handleChannelClick={handleChannelClick}
channelUrl={channelInfo.channelUrl}
key={index}
src={channelInfo.channelThumbnail}
alt={`Thumbnail ${index + 1}`}
/>
<p>{channelInfo.channelTitle}</p>
</BestYoutuber>
))}
</MainBestContWrap>
</MainBest>
</MainWrap>
);
}