React Ver - westagram 추가 기능 후기🤩

Solmii·2020년 6월 17일
3

Project

목록 보기
6/14
post-thumbnail
post-custom-banner

   Nav bar - 검색창 클릭시 레이아웃 변경   

하....잘하다가 막판에 cancel 버튼 (X버튼) 때문에 좀 힘들었다😭

왜 막혔는지랑 어떻게 해결했는지는 밑에서 정리하고, 일단 검색창 코드부터 gogo!

this.state = {
  searchClick: false,
  searchInput: '',
};

일단 초기 statesearchClick , searchInput 값을 지정해준다.

searchOnHandler = () => { // onFocus 이벤트
  this.setState({ searchClick: true }); 
};
searchOffHandler = () => { // onBlur 이벤트
  this.setState({ searchClick: false }); 
};
setSearchHandler = (e) => { // input 창에 onChange 이벤트
  this.setState({
    searchInput: e.target.value,
  }); 
};

이벤트는 searchClick 이라는 상태만 true/false 로 계속 변경해주고,
css에서 포커스 됐을때와, 포커스를 잃었을때의 검색창 디자인 2가지를 만들어준다.

그리고 각 input창이나 icon 의 className 에서 삼항연산자를 이용해서 searchClick 상태에 따라 변경될 수 있게 했다.

처음에는 이런식으로 했었다!

<div> // onFocus, onBlur 이벤트
	<img search_icon/>
	<button cancel_icon/>
	<input 검색창/> // onChange 이벤트
</div>

이렇게 걸어주니까 잘 동작했는데...

찐스타그램을 보면 X버튼을 클릭했을때, 다시 클릭하기전 검색창으로 돌아간다.
나는 안돌아간다. 돌아가게 만들어 줘야지!

에서부터 이제 문제의 cancel 버튼 뜯어고치기 여정이 시작된다...........ㅠ

댓글창과 마찬가지로,

searchInputRemoveHandler = () => {
    this.setState({
      searchInput: '',
			searchClick: false,
    });
  };

처음 검색창으로 돌아갈 수 있도록 searchClick의 상태를 바꿔주고, input value를 지워주는 이벤트를 하나 만들었다.
input 창에 value={this.state.searchInput} 를 지정해주고, X 버튼에 onClick 이벤트를 걸어주었는데.....

문제는 X버튼이 onFocus, onBlur 이벤트가 걸린 div 보다 하위에 있어서, 버튼이 눌리지 않는 것이다ㅠㅠ
(그러니까 버튼이 눌리기 전에, input 창 바깥이 먼저 클릭되서 onBlur 이벤트가 먼저 실행되어 버리고, X버튼은 없어진다......)

결국 종택님께 도움 요청 ㅠㅠㅠㅠㅠㅠㅠㅠ

여러가지 방법이 있지만 종택님 본인이라면 cancel_icon 을 상단으로 뺄거라고 하심!

<div 새로만듬>
  <button cancel_icon/>
  <div>
    <img search_icon/>
    <input 검색창/>
  </div>
</div>

이렇게 구조를 변경해줬다.

근데 이번엔 X 버튼이 보이지 않는 문제가....!!

다시 종택님께 달려갔더니, .cancel_icon 의 css에 이런 속성을 추가해주셨다.

z-index: 100;

( z-index의 값이 항상 100이어야 하는건 아니다. 양의 정수이기만 하면 됨)

💁🏻‍♀️ z-index 란?

엘리멘트들이 어떻게 쌓이는지 결정하는 속성이다.
여기서 쌓인다는 의미는 엘리멘트들이 어떻게 포개지는지를 말한다.
포토샵의 레이어를 생각하면 쉽다. 숫자가 낮을수록 하위 레이어, 높을수록 상위 레이어다.
단, z-indexposition 속성이 설정된 엘리먼트에 대해서만 동작한다.
왜? 그야, position 속성으로 겹치는게 아니라면, 엘리멘트들이 겹쳐질 일이 없으니까!!!
이런 느낌임!

그러니까 즉, X버튼은 안보였던 게 아니라 위의 input 창에 포개져서 안보였던것...!!

z-index 주니까 해결되었다!

이렇게 동작한다!


   Main page - Heart 버튼 누르면 애니메이션!   

인스타그램에서 좋아요 버튼을 누르면 빨갛게 칠해지면서 살짝 커졌다가 작아진다.

그부분을 구현해보기로!!!

constructor(props) {
    super(props);
    this.state = {
      btn_color: true,
    };
  }
  btnChangeHandler = () => {
    this.setState({ btn_color: !this.state.btn_color });
  };

state 초기 설정할 때, btn_color 라는 key 에 true 라는 값을 할당해준다!

btnChangeHandler 라는 이벤트는 click 이벤트로 걸어주고, 요 아이는 클릭할 때 마다 true/false 값을 바꿔주는 역할을 한다!

그 후에, 클릭할 때 마다 boolean 값이 바뀌는 요 this.state.btn_color 라는 녀석을 여기저기 다 이용해주면 된다!!

일단 css에 버튼 스타일을 2개 만들어놓고,

className={this.state.btn_color ? 'off_button' : 'on_button'}

요렇게 하트가 눌릴때 마다 class가 변경될 수 있도록 해주었다!

참고로, css에서 @keyframes 도 같이 걸어서, 0% 100% 에서는 width:100% 로, 50% 에서는 width:125% 정도로 애니메이션을 걸어주었다.

찐스타그램에서 보니까 path 자체도 바뀌어서 (테두리만 있는 하트, 꽉 찬 하트) className 변경할때랑 같은 방식으로 path 값도 바꿔주었다!

이렇게 동작함😘!!!!


   Main page - 댓글 수 카운트   

<div className='more_comment'>
  <a href=''>댓글 {this.state.commentArr.length + 2}개 모두 보기</a>
</div>

그리고 댓글 2개 모두 보기 부분이 그때그때 바뀔 수 있도록 this.state.commentArr.length + 2 를 넣어주면 끝!! 간단쓰~~~

+ 2 는 먼저 댓글단 두 분이 있어서ㅋㅋㅋㅋㅋ넣었음

이렇게 댓글이 하나씩 늘어난다!!!


   Main page - 댓글 삭제   

지옥의 댓글 삭제......😅

Uploadcomment component 에 아래와 같은 이벤트를 추가해준다.

  commentDelHandler = (index) => {
    this.setState({
      commentArr: this.state.commentArr.filter((_, idx) => idx !== index),
    });
  };

commentDelHandler 라는 함수는 index 를 파라미터로 받아 오는데, 이 index 는 아래에서 map 돌면서 댓글을 계속 추가해주는 <CommentForm />index 를 말한다.

commentArr 의 값을 commentArrfilter 돌린 값으로 setState 해준다.

filter_ ( commentArr 의 요소인데, 안쓸거라서 _ 라고 썼음. idxfilter 메서드의 2번째 파라니터인데, 해당 배열의 index 값을 의미한다.)

즉, commentArridx(index)가 <CommentForm />index 와 일치하지 않은 것만 반환하여 commentArrsetState 해주는 것!!

이제 아래에서 댓글을 클릭 할때마다 <CommentForm />index 값을 받아와서, commentArridx = 등록되어 있는 댓글 과 <CommentForm />index = 유저가 click한 댓글 의 index의 일치여부를 commentDelHandler 함수로 확인할거당!!

만약 인덱스가 일치하면? 그 댓글만 삭제하면 된다! 삭제는 어떻게 구현할까?

filter 를 이용하면 테스트를 통과한 댓글만 다시 반환해주니까, idx !== index 이라고 쓰면된다.
(idx === index 만 삭제랑 같다!)

map 으로 돌리는 component에 props로 해당 이벤트를 넘겨준다.

{this.state.commentArr.map((userInput, idx) => (
  <CommentForm name='Wecoder' comment={userInput} key={idx} index={idx} commentDelHandler={this.commentDelHandler} />
))}

나는 삭제 버튼을 따로 만들지 않고 (안예뻐서....)

그냥 댓글 내용을 클릭하면 바로 댓글이 삭제 되도록 아래의 위치에 이벤트를 걸었다.

CommentForm

<span onClick={() => this.props.commentDelHandler(this.props.index)}>{this.props.comment}</span>

고작 한줄인데 무지 어렵다.

대충 뭔말이냐면.... onClick 때 이벤트가 실행되는데.... 그 이벤트는 Uploadcomment 에서 props로 넘겨준 이벤트다.

근데 이 이벤트는, 함수이므로, 인자를 받을 수 있다.

CommentForm 에서 map으로 돌리는 <Component index={idx} /> 의 저기 저녀석!!!!

index를 인자로 넘겨준다.

(여기서 이 index 는 실제로는 map 함수의 두번째 인자로서, 자동으로 뽑아내지는 댓글의 index이다.)

arrow function으로 넘겨준 이유는 댓글을 click 해야지만 함수가 실행될 수 있도록, 콜백 함수로 넘겨준것이다.

이부분 아직 많이 헷갈려서 다시 진행 순서를 정리해보았다.

파라미터로 index를 받는 commentDelHandler 함수 정의(이하 Del) → <CommentForm /> 한테 props로 Del 함수 전달 → <CommentForm /> 에서 Del 함수 전달 받아서, <span> 태그 안에 onClick 이벤트로 Del 함수 전달 (이 때 형태는 콜백 함수) → <CommentForm />index 를 props로 Del 함수의 인자로 넘겨준다!

이렇게 댓글을 클릭하면 삭제된다!


진짜 끝!!!!!!!!!!!!1

profile
하루는 치열하게 인생은 여유롭게
post-custom-banner

0개의 댓글