Westagram 프로젝트_ 코드 리뷰

이병수·2020년 7월 19일
0

Westagram Cloning Project

개발 기간 : 6.29~ 7.19 (2주, 자바스크립트) , 7.13~7.19 (1주 리액트)
개발 목적 : 전세계 가장 영향력있는 소셜 미디어 플랫폼인 인스타그램 클로닝
구현 기능 :
1) (로그인페이지) 아이디,비밀번호 입력 시 로그인 버튼 색깔 변경
2) (로그인페이지) 미리 설정한 아이디, 비밀번호 입력해야 메인 페이지 이동 가능
3) (로그인페이지) 비밀번호 틀릴 시 '비밀번호 틀렸습니다'
4) (메인 페이지) 댓글 기능 구현
5) (메인 페이지) 댓글 삭제 기능 구현

로그인 페이지


class Login extends React.Component {
  constructor() {
    super();
    this.state = {
      backgroundColor : "",
      id : "",
      password : "",
      ready : false,
      myId : "djaxornwkd12@gmail.com",
      myPassword :"qudtn12",
      passwordError : false
    }
  }

  inputIdValue = (e) => {
    this.setState({
      id : e.target.value
    })
  }
  
  inputPasswordValue = (e) => {
    this.setState({
      password : e.target.value,
      ready : e.target.value.length>5&&this.state.id.includes('@') ? true : false
    })
    
  }
  

1) inputIdValue,inputPasswordValue라는 변수에 호출 시 동작되는 함수를 담았고 setState으로 id값,password값 인풋 입력 시 state값 변경될 수 있게 만들었다

2) 패스워드에는 id값과 password값 특정 조건 충족시 state의 ready 값의 밸류를 트루로 바꿔준다
그래서 밑의 <button className={this.state.ready ? "login ready" : "login btn"} 에 의해 button의 클래스네임 변경되어 바뀐 css가 적용되게 된다.

✅ 위와같이 className에 바로 삼항연산자 쓰는 방식은 자주 쓰인다!


  goToMainPage = (e)=> {
    const { id,password,myId,myPassword } = this.state
    if(id=== myId && password === myPassword) {
      this.props.history.push('/main-byeongsoo')
    }
    else {
      this.setState({
        passwordError : true 
      })
    }

1) destructuring으로 this.state.라고 일일이 써주는 것을 간결하게 해준다 참고사이트
2) this.props.history.push로 페이지 이동
3) input에 입력한 id값과 password값이 미리 state에 설정한 myId, myPassword값아 일치 시 메인 페이지로 이동
4) 틀릴 시 passwordError state 키값 밸류 true로 변경 -> <div className={this.state.passwordError ? "error":"noError"}>잘못된 비밀번호입니다. 다시 확인하세요</div>에 의해 className변경 hidden되어 있던 visibility visible로 변경

✅ visibility : hidden or visible로 특정 조건일 때만 보이게 만들 수있다

        .noError {
            visibility: hidden;
        }
        
        .error {
            visibility: visible;
            font-size: 15px;
            font-weight: bold;
            color : red;
        }

    fetch("http://10.58.0.223:8000/user/signin", {
      method :"POST",
      body : JSON.stringify({
        email:this.state.id,
        password: this.state.password
      })
    })
    .then(res => res.json()) // JSON body -> JS
    .then(res => sessionStorage.setItem("access_token", res.access_token))
  }


  render() {
    return (
      <div className="Login_BS">
        <div className="Wrapper">
            <div className="logo">
                <img src = "/images/byeongsoolee/logo_text.png" alt="메인로고" />
            </div>
            <div className="InfoBox">
                <input type="text" value={this.state.id} onChange={this.inputIdValue} className="login contents id" placeholder="전화번호, 사용자 이름 또는 이메일" />
                <input type="password" value={this.state.password} onChange={this.inputPasswordValue} className="login contents pwd" placeholder="비밀번호" />
                <button className={this.state.ready ? "login ready" : "login btn"}
                 onClick={this.goToMainPage}>로그인</button>
            </div>
            <div className={this.state.passwordError ? "error":"noError"}>잘못된 비밀번호입니다. 다시 확인하세요</div>
            <div className="forgetPwd">비밀번호를 잊으셨나요?</div>
        </div>
      </div>  
    );
  }
}

export default Login; 

메인페이지 (Nav,Feed,mainRight)

Feed

import React from "react";
import "./Feed.scss";

class Feed extends React.Component {
  constructor(props) {
    super();

    this.state = {
      comments: [
        "tottenham_official wow Jisung Park is my favorite player!",
        "real_madrid_official Jisung Park is a living lenged",
      ],
      typeComment: "",
    };
  }

  textChange = (e) => {
    this.setState({
      typeComment: e.target.value,
    });
  };

  add = () => {
    const { comments, typeComment } = this.state;
    typeComment.length !== 0 &&
      this.setState({
        comments: comments.concat(`hm_son7 ` + typeComment),
        typeComment: "",
      });
  };

1) add라는 변수만 어떤 동작을하는 함수인 지 파악하기 힘들다->✅ 함수명은 그것만 봐서 알 수 있는 적절한 이름으로 지어야한다
2) add라는 함수로 댓글 입력 시 추가되는 기능 구현을 했다✌️ state으로 정의했던 comment배열에 concat method로 내가 입력한 것(typeComment)을 붙여주는 방식으로 구현했다.

  handleKeyPress = (e) => {
    e.keyCode === 13 && this.add();
  };

버튼에 onClick을 줬지만 인풋에서 엔터 시 댓글이 추가될 수 있도록 onKeyUp={this.handleKeyPress}를 걸었다! 👍

  handleDelete = (index) => {
    const tempArr = this.state.comments.slice(0, index);
    const afterDeleteArr = this.state.comments.slice(index + 1);
    this.setState({
      comments: [...tempArr, ...afterDeleteArr],
    });
  };

제일 힘들게 작성한 코드 😂 사실 준식님,종택님의 도움으로 완성한 코드지만 제일 애착이 큰 코드
1) slice의 특성을 활용해 해당 댓글 (index)만 제외 그 전 댓글들과 그 후 댓글들을 분리했고
spread operator를 활용해 state의 comments의 배열 값이 바뀌게 만들었다


  render() {
    const commentList = this.state.comments.map((typeComment, index) => {
      return (
        <li className="replyList" key={index}>
          {typeComment}
          <span className="imgList">
            <span onClick={() => this.handleDelete(index)}>삭제</span>
          </span>
        </li>
      );
    });

    return (
      <div className="Feed_BS">
        <div className="feedsContainer">
          <div className="header">
            <div className="profile">
              <img
                alt="맨유 프로필"
                src="https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-19/s320x320/95389054_555222165374068_542779107667083264_n.jpg?_nc_ht=scontent-gmp1-1.cdninstagram.com&_nc_ohc=m6OgKSZDdncAX83Bmgk&oh=ba627dce6632eb1cd73943c1624731d0&oe=5F2645D0"
              />
              <p>manchester_united</p>
            </div>
            <img
              alt="..."
              src="https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/more.png"
            />
          </div>
          <div className="feedPic">
            <img
              alt="박지성 사진"
              src="https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-15/e35/104418570_713138709525676_2431057879476108410_n.jpg?_nc_ht=scontent-gmp1-1.cdninstagram.com&_nc_cat=104&_nc_ohc=YI7DZfikd18AX8Lf6mh&oh=3c02c1a82078b7b6ffd33608a6b8b376&oe=5F232C00"
            />
          </div>
          <div className="feedLogo">
            <div className="feedLogoLeft">
              <img
                alt="하트"
                src="https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/heart.png"
              />
              <img
                alt="말풍선"
                src="https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/comment.png"
              />
              <img
                alt="공유"
                src="https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/share.png"
              />
            </div>
            <img
              alt="북마크"
              src="https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/bookmark.png"
            />
          </div>
          <div className="feedReply">
            <div className="replyLikeTotal">
              <img
                alt="토트넘 프로필"
                src="https://scontent-gmp1-1.cdninstagram.com/v/t51.2885-19/s320x320/91813079_951055115342792_3781464304625123328_n.jpg?_nc_ht=scontent-gmp1-1.cdninstagram.com&_nc_ohc=ctRc2X7wrHYAX9MMcfT&oh=84bfa84d58a12c228a70cada7426ba18&oe=5F24D9AF"
              />
              <p>tottenham_official님 외 7천명이 좋아합니다</p>
            </div>
            <div className="replyContent">
              <ul>{commentList}</ul>
            </div>
            <div className="replyTime">
              <p>42분 전</p>
            </div>
          </div>
          <div className="feedComment">
            <input
              type="text"
              value={this.state.typeComment}
              onChange={this.textChange}
              onKeyUp={this.handleKeyPress}
              className="commentBox"
              placeholder="댓글 달기..."
            />
            <button onClick={this.add} className="commentBtn">
              게시
            </button>
          </div>
        </div>
      </div>
    );
  }
}

export default Feed;

Code Review

**import 순서는 보통 패키지 > 컴포너트 > 이미지 파일 > .scss 순이 좋다

** 최상단의 감싸주기 위한 div는 React Fragment 를 사용하는 것이 좋다!

       <div>   // <>
            <div>
                <Nav />
            </div>
            <div className ="mainContainer">
                <Feed />
                <MainRight />
            </div>
        </div> //<>

변수명은 그것 자체만으로 어떤 의미인지 직관적으로 파악이 되어야 한다.

<<myCode


this.state = {
      backgroundColor : "",
      id : "",
      password : "",
      ready : false,
      myId : "djaxornwkd12@gmail.com",
      myPassword :"qudtn12",
      passwordError : false
    }
         

여기서 state 값으로 ready를 줬지만 그 자체로 어떤 준비? 인지 알기 힘들다

         
  inputPasswordValue = (e) => {
    this.setState({
      password : e.target.value,
      ready : e.target.value.length>5&&this.state.id.includes('@') ? true : 	  false
    })
    
  }
   <button className={this.state.ready ? "login ready" : "login btn"}
                 onClick={this.goToMainPage}>로그인</button>

결국 ready는 btn의 색깔을 바꾸기 위한 조건이므로 isBtnValid등의 변수명이 적절하다

0개의 댓글