For Programmer

8. 구독기능 구현(1) - 유튜브 클론 코딩 본문

React & Node.js 프로젝트/유튜브 클론 코딩

8. 구독기능 구현(1) - 유튜브 클론 코딩

유지광이 2020. 7. 23. 21:02
728x90

1. Subscriber Model 만들기: server -models - Subscriber.js 생성

2. Subscriber.js 몽구스 DB 코드

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const subscriberSchema = mongoose.Schema(
  {
    userTo: {
      type: Schema.Types.ObjectId,
      ref: "User",
    },
    userFrom: {
      type: Schema.Types.ObjectId,
      ref: "User",
    },
  },
  { timestamps: true }
);
const Subscriber = mongoose.model("Subscriber", subscriberSchema); //1st모델의이름,2nd데이터

module.exports = Subscriber; //다른파일에서사용가능

3. 서버에 Axios통신을 위한 subscribe.js 라우터 만들기(server-routes-subscribe.js)

const express = require("express");
const router = express.Router();
const Subscriber = require("../models/Subscriber");

//=================================
//             Subscribe
//=================================

router.post("/subscribeNumber", (req, res) => {
  Subscriber.find({ userTo: req.body.userTo }).exec((err, subscribe) => {
    if (err) return res.status(400).send(err);
    return res
      .status(200)
      .json({ success: true, subscribeNumber: subscribe.length });
  });
});

router.post("/subscribed", (req, res) => {
  Subscriber.find({
    userTo: req.body.userTo,
    userFrom: req.body.userFrom,
  }).exec((err, subscribe) => {
    if (err) res.status(400).send(err);
    let result = false;
    if (subscribe.length !== 0) {
      result = true;
    }
    res.status(200).json({ success: true, subscribed: result });
  });
});
module.exports = router;

4. 리액트에서 화면에 출력하기 위한 버튼 만들기(구독정보,구독자수를 받아오기위한 Axios통신 포함코드) ,(client-src-components-views-VideoDetailPage-Sections-Subscribe.js)

import React, { useState, useEffect } from 'react';
import Axios from 'axios';

function Subscribe(props) {
  const [SubscribeNumber, setSubscribeNumber] = useState(0);
  const [Subscribed, setSubscribed] = useState(false);

  useEffect(() => {
    let variable = { userTo: props.userTo };
    Axios.post('/api/subscribe/subscribeNumber', variable).then((response) => {
      if (response.data.success) {
        setSubscribeNumber(response.data.subscribeNumber);
      } else {
        alert('구독자 수 정보를 받아오지 못했습니다.');
      }
    });
    let subscribedVariable = {
      userTo: props.userTo,
      userFrom: localStorage.getItem('userId'), //로그인할때 userId에 userId값을 넣어놨었음
    };

    Axios.post('/api/subscribe/subscribed', subscribedVariable).then(
      (response) => {
        if (response.data.success) {
          setSubscribed(response.data.subscribed);
        } else {
          alert('정보를 받아오지 못했습니다.');
        }
        console.log(Subscribed);
      }
    );
  }, []);
  return (
    <div>
      <button
        style={{
          backgroundColor: `${Subscribed ? '#AAAAAA' : '#CC0000'}`,
          borderRadius: '5px',
          color: 'white',
          padding: '10px 16px',
          fontWeight: '500',
          fontSize: '1rem',
          textTransform: 'uppercase',
        }}
        onClick
      >
        {SubscribeNumber} {Subscribed ? 'Subscribed' : 'Subscribe'}
      </button>
    </div>
  );
}

export default Subscribe;

5. VideoDetailPage.js에서 화면에 버튼을 만들기 위해 actions 값 주기 (antd CSS 이용)

...생략
if (VideoDetail.writer) {
    const subscribeButton = VideoDetail.writer._id !==
      localStorage.getItem('userId') && (
      <Subscribe
        userTo={VideoDetail.writer._id}
        userFrom={localStorage.getItem('userId')}
      /> //만약 페이지의 동영상이 본인의 동영상이면 구독버튼을 안보이게만든다.
    );
    //witer를 서버에서 가져오기전에 페이지를 렌더링 할려고해서
    //VideoDetail.writer.image 부분에서 type error가 발생한다.
    return (
      <Row gutter={(16, 16)}>
        <Col lg={18} xs={24}>
          <div style={{ width: '100%', padding: '3rem 4rem' }}>
            <video
              style={{ width: '100%' }}
              src={`http://localhost:5000/${VideoDetail.filePath}`}
              controls
            />
            <List.Item actions={[subscribeButton]}>
              <List.Item.Meta
                avatar={<Avatar src={VideoDetail.writer.image} />}
                title={VideoDetail.writer.name}
                description={VideoDetail.description}
              />
            </List.Item>
            {/* comment*/}
          </div>
        </Col>
        ...이하생략

실행결과

 

해당강의

 

728x90
Comments