안녕하세요

2주차 유튜브 API(5) - 구독 기능, 좋아요 표시한 동영상, 리덕스 이식 본문

복습스터디과제

2주차 유튜브 API(5) - 구독 기능, 좋아요 표시한 동영상, 리덕스 이식

sakuraop 2023. 1. 24. 05:20

https://youngentry.github.io/week2-youtube-api/

 

React App

 

youngentry.github.io

구독 기능 만들기

=> 버튼을 클릭하면 눌려있는 표시로 바뀐다.

 

 

  useEffect(() => {
    axios
      .get(`https://youtube.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=25&key=${apiKey}`)
      .then((res) => {
        dispatch(setPopularVideo([...res.data.items]));
      })
      .catch((error) => console.log("error", error));
  }, []);

=> App.js에서 GET 요청으로 인기 동영상을 받아옵니다.

=> 받아온 동영상 목록을 popularVideo state에 저장합니다.

 

 

=> 구독한 채널을 사이드에 별도로 렌더링하기 위해서는 여러 컴포넌트에 state를 사용해야 한다는 판단에 리덕스로 state를 옮겼습니다.

 

 

=> 구독한 채널을 사이드바에서 볼 수 있도록 했습니다.

 

 

Video.js(동영상페이지)에서 좋아요, 싫어요, 구독중 상태를 관리할 스테이트를 만듭니다.

  const tempListIndex = popularVideo.findIndex((data) => data.id === mockVideo.id);
  const [isLike, setIsLike] = useState(popularVideo[tempListIndex].isLike);
  const [isDislike, setIsDislike] = useState(popularVideo[tempListIndex].isDislike);
  const [isSubscribed, setIsSubscribed] = useState(popularVideo[tempListIndex].isSubscribed);

=> 초기값은 popularVideo에서 동영상페이지의 id와 일치하는 동영상의 좋아요, 싫어요, 구독중 상태로 만듭니다.

=> 동영상페이지를 나갔다 돌아올 때도 버튼이 눌려있는 상태를 유지합니다.

 

 

 

subscribe 함수를 실행하면 subscribeList에 데이터를 추가합니다.

  const subscribe = () => {
    setIsSubscribed(!isSubscribed);
    dispatch(addSubscribe({ title: mockVideo.snippet.channelTitle, channelId: mockVideo.snippet.channelId }));
  };
  
  
  // html
                <div className={`subscribe`} onClick={() => subscribe()}>구독</div>

=> 구독하기 버튼을 누르면 버튼이 눌리는 상태로 변하게 되고,

=> subscribeList state에 구독한 채널의 이름과 채널 id를 추가합니다.

=> channel Id를 함께 담아 채널 이름을 클릭하면 해당 채널로 이동하는 기능을 구현할 것입니다.

 

 

 

다음으로는 구독 버튼을 클릭하면 subscribeList state에 저장한 데이터를 이용해  NavSide에 나타나게 합니다.

=> 구독 버튼을 클릭하면 이렇게 사이드 네비에 나타나도록 합니다.

 

 

subScribeList state를 NavSide component에 가져옵니다.

const NavSide = () => {
  const subscribeListSlice = useSelector((state) => state.subscribeListSlice);

 

 

구독 목록이 비어있다면 "없음"을 출력하고 구독한 채널이 있다면 해당 채널을 표시합니다.

      <div className="side-container">
        <strong>구독</strong>
        {subscribeListSlice.length ? (
          subscribeListSlice.map((channel) => {
            return <div className="subscribe-side-list">{channel.title}</div>;
          })
        ) : (
          <div className="subscribe-side-list">없음</div>
        )}
      </div>

 

a 태그를 이용하여 해당 채널을 새 탭에서 띄우는 기능을 구현합니다.

(채널 페이지까지 구현하기 위해서는 너무 오래 걸릴 것 같아 새 탭 띄우기로 대체합니다.)

  const channelBaseUrl = "https://www.youtube.com/channel/";

=> 위의 url 뒤에 channelId를 입력하면 됩니다.

 

              <div className="subscribe-side-list">
                <a href={`${channelBaseUrl}${channel.channelId}`} target="_blank">
                  {channel.title}
                </a>
              </div>

=> target="_blank" 속성을 주게 되면 새 탭에서 띄웁니다.

 

=> 채널 글씨에 마우스를 얹으니 연결 링크가 나타납니다.

 

 

subscribe 페이지도 subscribeList를 가져다 만들어 봅시다.

const Subscribe = () => {
  const channelBaseUrl = "https://www.youtube.com/channel/";
  const subscribeList = useSelector((state) => state.subscribeListSlice);

  console.log(subscribeList);
  return (
    <div className="subscribe">
      <h2>구독한 채널 목록</h2>
      {subscribeList.map((channel, index) => {
        return channel ? (
          <div key={index}>
            <a href={`${channelBaseUrl}${channel.channelId}`} target="_blank">
              {channel.title}
            </a>
          </div>
        ) : (
          <div key={index}>{null}</div>
        );
      })}
    </div>
  );
};

=> NavSide 만들때랑 똑같이 만들면 됩니다.

 

=> 잘 됩니다.


Like, Dislike component도 동일한 방식으로 만드는 것이 관리도 쉽고 현실적이겠지만...

구독 기능 구현과 완전하게 똑같은 과정을 반복하면 될 뿐이어서💦

data에 isLike 속성을 넣어주고, isLike 속성을 가진 영상을 출력하도록 했습니다.

    setLike(state, action) {
      state[action.payload.tempListIndex].isLike = action.payload.isLike;
    },

=>  setLike 함수를 실행하면 popularVideo의 데이터에 isLike 속성을 업데이트 합니다.

 

=> isDisLike, isLike, isSubscribed 데이터가 업데이트 된 모습

 

Like 페이지에서 isLike 속성을 가진 영상을 골라서 렌더링합니다.

const Like = () => {
  const popularVideo = useSelector((state) => state.popularVideo);

  return (
    <div>
      <div>좋아요 표시한 동영상</div>
      {popularVideo.map((data, index) => {
        return data.isLike ? (
          <div key={index}>
            <div>
              <ReactPlayer className="videoPlayer" url={`https://www.youtube.com/embed/${data.id}&origin=http://localhost:3000/`} muted={true} playing={false} width="100%" height="100%" />
            </div>
            <strong> {data.snippet.title}</strong>
          </div>
        ) : (
          <div key={index}>{null}</div>
        );
      })}
    </div>
  );
};

 

=> 좋아요 표시를 남긴 동영상과 동영상의 제목을 같이 나타나도록 했습니다.

 

=> 싫어요 페이지도 똑같은 방식으로 만들어 줍니다.


리덕스 이식 과정은 store.js 코드로 대체합니다.

(지금 프로젝트 만들다 시간 지나면 까먹어서 다음 프로젝트 할 때는 어차피 또 어떻게하더라... 하면서 찾아봐야 합니다.

기억하려면 시간들여 반복하는 수 밖에 없죠.🙄)

import { configureStore, createSlice } from "@reduxjs/toolkit";

const popularVideo = createSlice({
  name: "popularVideo",
  initialState: [],
  reducers: {
    setPopularVideo(state, videoList) {
      return [...videoList.payload];
    },

    setLike(state, action) {
      state[action.payload.tempListIndex].isLike = action.payload.isLike;
    },

    setDislike(state, action) {
      state[action.payload.tempListIndex].isDislike = action.payload.isDislike;
    },

    setSubscribe(state, action) {
      state[action.payload.tempListIndex].isSubscribed = action.payload.isSubscribed;
    },
  },
});

export let { setPopularVideo, setLike, setDislike, setSubscribe } = popularVideo.actions;

const subscribeListSlice = createSlice({
  name: "subscribeListSlice",
  initialState: [],
  reducers: {
    addSubscribe(state, action) {
      return [...state, action.payload];
    },
  },
});

export let { addSubscribe } = subscribeListSlice.actions;

export default configureStore({
  reducer: {
    popularVideo: popularVideo.reducer,
    subscribeListSlice: subscribeListSlice.reducer,
  },
});

4번 구독기능 마지막 기능 제외하고 구현 완료🙆‍♀️

➕구독한 영상 상단으로 기능 추가하기