[TIL]React/Typescript React-query,Router, FramerMotion을 사용한 영화 사이트 만들기

ohoho·2024년 11월 7일

슬기로운스터디

목록 보기
42/54

오늘 공부한것 & 기억할 내용

React-query,Router, FramerMotion을 사용하여 영화 사이트를 만들었다.

1. 문제

Header.tsx안에 Home, Comming, Now 컴포넌트를 넣어 해당 페이지로 이동할때마다 Title아래에 Circle이 생기도록 작업하였다.
이때 useMatch를 사용하여 url이 true면 Circle을 추가하여 작업했는데 영화 클립시 팝업이 열리면서 url이 변경되어 Circle이 지워지는 문제가 발생하였다.

해결

useMatch대신 useLocation을 사용하여 url의 주소를 받아온 뒤
home.pathname.split('movie')[0] movie의 앞자리만 반환하여 조건문을 사용하여 true면 Circle가 노출되도록 작업하였다.

  const home = useLocation();
  const result = home.pathname.split('movie')[0];
  return (
    <>
      <HeaderWrap>
        <Link to={'/'}>
          POPULAR{result === '/' && <Circle layoutId="circle" />}
        </Link>
        <Link to={'/coming-soon'}>
          Coming Soon
          {result.includes('/coming-soon') && <Circle layoutId="circle" />}
        </Link>
        <Link to={'/now-playing'}>
          Now Playing
          {result.includes('/now-playing') && <Circle layoutId="circle" />}
        </Link>
      </HeaderWrap>
    </>
  );

코드리뷰 배울점

스터디원들의 코드를 보면서 같은 결과물이지만 그 안의 코드가 정말 다르다고 느껴졌다.
그 중 두가지가 너무 인상 깊다.

  1. Search검색 기능
    활성화 되어 있는 탭에서 내가 찾고자 하는 영화가 있는지 검색하는 기능
//Search.tsx
//props로 searchText,setSearchText 를 받아온다.
function Search({
  searchText,
  setSearchText,
}: {
  searchText: string;
  setSearchText: React.Dispatch<React.SetStateAction<string>>;
}) {
  function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    //검색한 input을 지워주는 역할
    setSearchText('');
  }

  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    //onChange될때마다 value값이 들어간다.
    setSearchText(e.target.value);
  }
  return (
    <Form onSubmit={handleSubmit}>
      <Input onChange={handleChange} value={searchText} />
    </Form>
  );
}

//List.tsx
const [searchText, setSearchText] = useState('');

<Search searchText={searchText} setSearchText={setSearchText} />
  <Items variants={ItemsVariants} initial="hidden" animate="visible">
    {movies
     .filter((movie) => {
       if (searchText) {
         //movie(data) title안에 searchText 가 포함하고 있으면 그것을 리턴해 map으로 뿌려주고
         return movie.title.includes(searchText);
       } else {
         // 아니라면 종료한다.
         return true;
       }
     })
       .map((movie) => (
         <Movie key={movie.id} movie={movie} setMovieId={setMovieId} />
         ))}
  1. 카드 클릭시 팝업 노출되도록 작업
    Card에 setId(movie.id)로 id값을 넣어주고 id값이 있을때만 팝업을 보여준다.
    그리고 팝업을 다시 누르면 setId(null)값을 넣어서 팝업이 닫힌다.
const [id, setId] = useState(null);

<Card key={movie.id} movie={movie} onClick={() => setId(movie.id)} />

{id ? (
  <Overlay
  variants={overlayVariants}
  initial="hidden"
  animate="visible"
  exit="exit"
 >
   <DetailCard id={id} onClick={() => setId(null)} />
</Overlay>
) : null}

배운점 & 느낀점

이번 과제에서는 FramerMotion을 주로 썼는데 효과를 어디에 줘야하는지 혼란스러웠지만 삽질끝에 정확한 위치에 다들 들어간거 같아서 다행이다.
그리고 다른 사람들의 코드를 보면서 나와는 다른코드에 배울점이 많아보였다.
Search코드도 그렇고 팝업이 보이는것을 나는 location을 사용해 parameter에 있는 id값이랑 일치한다면 팝업이 보이게 했는데 그냥 카드에 아이디값 넘겨줘서 보일지 말지 구현하는것도 간단한 방법이라는것을 배웠다.

//내코드
const location = useLocation();
const { id } = useParams<{ id: string }>();
const isMatch = id && location.pathname.includes(id);

0개의 댓글