React | 인스타그램 클론 프로젝트 리뷰 ②

sunny·2021년 4월 10일
0
post-thumbnail

javascript로 구현했던 인스타그램 클론 코딩을 React로 바꿔보았다..😈 아래는 내가 기억하기 위해 남기는 블로깅이다..✍


state의 불변성

피드 내 댓글 작성 기능을 구현하는 과제를 받았다.
처음에 나는 💭 commentArr로 받아서 map을 돌려서 사용하니까 그냥 commentArr에 새 댓글 내용을 push하면 되는 거 아닐까!? 라고 생각했었다. (과거의 나..👊🏻💥)
react내에서의 state는 항상 불변성(변하지 아니하는 성질)이 지켜져야한다. array자체에 push를 하게 되면 원본 배열이 변하므로 react내에서 배열 state값을 업데이트해줘야할때는 concat 혹은 ES6 문법인 spread operator를 사용한다.
(react내에서 배열의 push에 관한 포스팅)

spread operator를 사용한 addComment 함수

  1. 게시 버튼을 누르는 순간 addComment 함수가 호출이 된다.
  2. comment의 내용이 있을때만 setState함수가 실행된다.
  3. spread operator를 사용해 전 commentArr와 새 commentArr 요소를 더해서 setState한다.
    • id는 commentArr의 길이의 +1을 해주므로 1부터 시작해서 댓글이 생성될때마다 1씩 증가한다.
    • 로컬스토리지에 저장된 userName이 없을 경우 임의로 지정한 defaultUser의 name이 userName이 된다.
  4. comment = ''로 댓글게시가 되면 input값을 비워준다.

함수의 전달 vs 호출

댓글 등록이 끝나고 추가로 댓글 좋아요, 삭제 기능을 구현해보고자 했다.
댓글 좋아요, 삭제 기능을 구현하려면 자식컴포넌트에서 부모 컴포넌트로 각 댓글의 아이디 값을 파라미터로 넘겨줘야했다.

처음엔 단순하게 javascript처럼 이런식으로 넘겨주려고했는데..

onClick={likeComment(id)}

응 오류😂

오류가 난 이유는 내가 쓴 코드가 함수를 전달하는 코드가 아닌 함수를 즉시 호출하는 코드였기때문이다.
함수에 파라미터로 데이터를 전달하는 방법은 여러가지가 있는데 그 중 한가지인 콜백에 화살표함수를 넣고 전달하는 방법을 사용했다.
(콜백 함수 실행 시 파라미터 전달하기)

onClick={() => likeComment(id)}

댓글 좋아요


onClick할때마다 해당 댓글의 id를 콜백 함수의 인자로 보내주고,

클릭할때 isLiked가 true면 false를 false를 true로 바꿔준다. isLiked의 상태에 따라 하트의 색이 바뀐다.

댓글 삭제

삭제 버튼을 누르면 확인창이 뜨고 사용자가 확인을 누른 경우에만 commentArr에 filter로 아이디가 같지 않은 (삭제버튼을 누르지 않은) 배열을 return해서 setState한다.


목데이터 활용

목데이터란?

실제 API 에서 받아온 데이터가 아닌 샘플로 만들어본 데이터

백엔드랑 붙여보기 전에 fetch함수를 사용해 목데이터를 불러와서 활용해보았다.
내 feed 목데이터의 일부!

id : 피드 고유 아이디
userName : 피드를 올린 유저 아이디
profileImg : 피드를 올린 유저의 프로필 이미지
feedImg : 피드 이미지
content : 피드 내용
registerDate : 피드를 올린 시간
likeList : 좋아요를 누른 사람들의 목록 (id, username, profile을 가진 객체로 이루어진 배열의 형태)
commentArr : 피드에 달린 댓글의 목록 (id, username, content, isLiked, likeAmount, registerDate 을 가진 객체로 이루어진 배열의 형태)

[
  {
    "id": 1,
    "userName": "dhdhdhtattoo",
    "profileImg": "18947565_448326618857685_84",
    "feedImg": "166777053_206041684187336",
    "content": "예약 가능합니다!",
    "registerDate": "1617688133",
    "likeList": [
      {
        "id": 1,
        "userName": "lalalalala",
        "profile": "18947565_448326618857685_8479464545633435648_a.jpg"
      },
      {
        "id": 2,
        "userName": "djsafld",
        "profile": "18947565_448326618857685_8479464545633435648_a.jpg"
      },
      {
        "id": 3,
        "userName": "123123",
        "profile": "18947565_448326618857685_8479464545633435648_a.jpg"
      },
      {
        "id": 4,
        "userName": "dsafdas",
        "profile": "18947565_448326618857685_8479464545633435648_a.jpg"
      },
      {
        "id": 5,
        "userName": "idididididdd",
        "profile": "18947565_448326618857685_8479464545633435648_a.jpg"
      }
    ],
    "commentArr": [
      {
        "id": 1,
        "userName": "otattoo",
        "content": "도안 예뻐요!",
        "isLiked": true,
        "likeAmount": 0,
        "registerDate": "1617688133"
      },
      {
        "id": 2,
        "userName": "meal-poke",
        "content": "짱귀욤",
        "isLiked": false,
        "likeAmount": 0,
        "registerDate": "1617688133"
      },
      {
        "id": 3,
        "userName": "yeoni-drawing",
        "content": "헐 ㅠㅠㅠㅠ",
        "isLiked": false,
        "likeAmount": 0,
        "registerDate": "1617688133"
      }
    ]
  }
]

componenDidMount 내에서 fetch함수로 feedData를 부른 뒤 setState로 feedArr을 업데이트해준다.
목데이터를 통한 여러개의 피드와 여러개의 댓글 구현 완료!🥰


config.js

API주소와 icon의 svg경로가 너무 길어서 html코드 내에서 관리하기가 힘들어 config.js 에 빼서 관리했다. 난 백엔드랑 통신할때 userName을 로컬스토리지에 저장해서 main에서 getItem으로 사용하고 있기 때문에 로컬스토리지 내 userName이 undefined일 경우 디폴트로 사용할 유저정보도 config.js 내에서 관리했다.
사용하는 icon의 svg경로는 icon.js를 따로 만들어 관리했다.

config.js

icon.js


백엔드와의 통신

백엔드와의 회원가입&로그인 통신에 관한 포스팅

추가로 백엔드분들과 업로드했을때 image url주고 받는 것도 해보고싶어서 구현해보았다. 화면에 백엔드로부터 받은 이미지가 뜨는 그 짜릿함이란!! 🤭

image upload

upload 후 db에 저장된 image url받아오기

받아온 데이터를 setState해준 후 화면에 뿌려주면 끝!🔥


리팩토링

모든 기능구현이 끝나고 코드의 가독성을 위해 리팩토링을 진행했다.
코드는 내가 쓰는 것보다 읽힐때가 더 많다는걸 기억하자!!

  1. 클래스명 변경
    html태그 클래스명은 -을 사용한 클래스명을 사용하고 js코드 클래스명은 카멜케이스를 사용했는데 모두 카멜케이스 형식으로 변경했다.

  2. 구조분해할당
    구조분해할당 (구조분해할당에 관한 포스팅)을 이용해 깔끔하게 리팩토링을 진행했다.

  3. import속성 순서 변경
    React > Pacakges, Library > Component > Style의 순서로 변경했다.

  4. css속성의 중요도에 따른 순서 변경
    레이아웃에 영향을 많이 미치는 순서대로, 비슷한 속성들끼리 묶어서 작성했다.

Layout Properties
(position, float, clear, display)
-> Box Model Properties
(width, height, margin, padding)
-> Visual Properties
(color, background, border, box-shadow)
-> Typography Properties
(font-size, font-family, text-align, text-transform)
-> Misc Properties
(cursor, overflow, z-index)
  1. 불필요한 주석 삭제
    주석은 개발할때만 남겨두도록 하자!

나름대로 꼼꼼하게 셀프 리팩토링했다고 생각했는데도 코드리뷰때 코멘트가 많이 달렸다 . ..🤓 전혀 생각못하고 있던 부분들을 지적해주셔서 도움이 많이 되었던 코드리뷰!!


수정사항 반영하고 pr올린 후 정말 마무리!!!!

짧은 후기 ,,

리액트.. 진짜 재밌다. 어려운데 진짜 재밌다!

profile
blog 👉🏻 https://kimnamsun.github.io/

0개의 댓글