위코드-TIL-16-react-위스타 이벤트 (메인)

jin_sk·2020년 6월 13일
0

위코드

목록 보기
36/49

메인 이벤트

댓글 입력 창에서 게시 버튼 누르거나 엔터누르면 댓글 업로드


constructor 생성

    constructor() {
        super();

        this.state = {
            inputComment: "",
            inputCommentUp: []
        }
        //this.handleChangeInput = this.handleChangeInput.bind(this);
        //this.clickCommentBtn = this.clickCommentBtn.bind(this);
    }
  • super(); 로 React.Component의 메서드 상속
    (부모클래스 생성자의 참조, super을 호출하기 전에는 this를 사용할 수 없음)

  • this.state로 component 속성의 상태 지정

  • 댓글 input 태그의 입력값을 받기 위한 inputComment생성

  • 댓글을 화면에 추가하기위한, 댓글 값을 담을 inputCommentUp 빈 배열 생성


댓글창 입력값 확인을 위한 함수 생성

 handleChangeInput = (e) => {
	this.setState({inputComment: e.target.value});
}
  • 댓글 input창에 입력값을 얻는 매개변수 설정 필수

  • 입력받은 e.target.value를 this.setState로 inputComment의 값 업데이트


게시 버튼 클릭 시 입력값이 배열에 추가되는 함수 생성

handelClickBtn = () => {
  // react에서 push 쓰는 법
  // react에서 state 내부의 값을 직접적으로 수정하면 안된다 
  // push, splice, unshift, pop은 배열 자체를 직접적으로 수정하므로 적합x
  // 기존 배열에 기반하여 새 배열을 만들어내는 concat, slice, map, filter 함수 사용
  // let inputArr = this.state.inputCommentUp;
  // let inputWord = this.state.inputComment;
  // inputArr.push(inputWord)
  // this.setState({inputCommentUp: inputArr})

  this.setState({
  	inputCommentUp: this.state.inputCommentUp.concat(this.state.inputComment)
  })
}
  • 맨 처음 push를 썼었는데 push는 함수가 아니라는 type error가 떴었다
    찾아보니 react에서 state 내부의 값을 직접적으로 수정하면 안돼,
    배열 자체를 직접적으로 수정하는 push 함수는 사용할 수 없고 간접적으로 변수를 선언해서 하는 것은 가능했다

  • concat을 쓰면 에러가나지 않는데,
    concat() 메서드는 인자로 주어진 배열이나 값들을 기존 배열에 합쳐서 새 배열을 반환한다
    참고 : MDN concat
    concat을 사용했더니 오류가나지 않았다

  • input 태그를 통해 입력받은 값을 this.setStateinputCommentUp에 값을 업데이트 한다

  • 의문점
    솔직히 왜 빈배열을 선언해야 되는지 정확히는 모르겠다
    태그자체를 배열의 요소로 본걸까?
    댓글을 추가할때 map함수를 써서 반환했는데 그 함수를 사용하려고 빈 배열에 값을 추가하는 것 같기도하다
    DOM에서는 그냥 태그를 생성하면 됐었던건데 편하면서도 원리를 완전히 이해하지는 못하겠다


input, button 태그에 이벤트 추가

  • 먼저 입력값을 저장하기 위해 댓글 입력 input 태그에 onChange 이벤트를 넣어준다
<input 
  className="a-c-i-addtext" 
  type="text" 
  placeholder="댓글 달기..."
  onChange={this.handleChangeInput}
/>
  • 게시버튼을 누르면 input에서 입력한 값을 배열에 추가하는 onClick 이벤트를 넣어준다
<button 
  type="button" 
  className="a-c-i-button"
  onClick={this.handelClickBtn}
>
  게시
</button>

map 함수로 댓글 form 추가

  • 기존 댓글 태그 밑에 map 함수로 댓글 구조 반환

  • 게시버튼을 클릭하면 onClick 이벤트가 발생하여 댓글 form이 추가 된다

{this.state.inputCommentUp.map((inputComment,idx) => {
  return (
    <div className="a-t-c-form" key={idx}>
      <a className="link a-t-c-userid" href="true">unknown user</a>
      <span className="a-t-c-content">{inputComment}</span>
      <button className="a-t-c-comment-del">삭제</button>
    </div>
  )
})}

  • map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다
    참고 : MDN map

  • 버튼을 클릭하기전 아직은 빈 배열인 inputCommentUp 을 불러와서 map 함수를 시행한다
    parameter 는 inputComment (input 태그 입력값), idx 키 값,
    return 값으로 댓글 구조를 반환한다

  • react에서 map 함수에서 key 는 필수로 들어가야 하고
    key는 배열을 렌더링을 할 때 꼭 필요한 값이라고 한다 (없어도 실행은 된다)
    react는 배열을 렌더링할 때 값을 통하여 업데이트 성능을 최적화한다
    아래 예를 통해서 좀 더 자세히 살펴보면

<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>

만약에 key를 부여하지 않으면, 배열의 index 값이 자동으로 key로 설정이되는데,
key가 배열의 인덱스로 설정되면 아래와 같이 보인다

<div key={0}>A</div>
<div key={1}>B</div>
<div key={2}>C</div>
<div key={3}>D</div>

배열의 index가 key 값으로 사용됐다

여기서 BC사이에 X를 추가한다고 하면 아래와 같이 보인다

<div key={0}>A</div>
<div key={1}>B</div>
<div key={2}>X</div> [C -> X]
<div key={3}>C</div> [D -> C]
<div key={4}>D</div> [새로 생성됨]

중간에 끼워넣기만하면 되는데,
배열의 index를 key로 사용하게되어 중간에 값이 들어가면 index도 바뀌어 추가된 값 밑으로 함께 변경되었다

key를 배열의 index 값으로 사용하는게 아니라, 데이터를 추가할 때마다 고정적인 고유 값을 부여해주면,
react가 변화를 감지해내고 업데이트를 하게 될 때 조금 더 효율적으로 처리할 수 있게 된다
고정적으로 값을 부여하면 아래와 같이 추가되어도 기존 key의 값은 변경되지 않는다

<div key={0}>A</div>
<div key={1}>B</div>
<div key={4}>X</div> // 새로 생성됨
<div key={2}>C</div> // 유지됨
<div key={3}>D</div> // 유지됨

결국 새로운 DOM은 하나만 생성되고, 나머지는 그대로 유지된다
key값은 언제나 고유해야 되기 때문이다

자세한 사항은 참고한 블로그에서 좀 더 자세히 볼 수 있다 (출처 : https://velopert.com/3636)


input 창에 엔터키를 입력하면 댓글을 추가하는 함수 추가

  • 이벤트가 발생할 때 전달되는 매개변수 e를 꼭 지정해줘야 한다

  • 입력되는 값의 e.keyEnter와 같으면 미리 만들어준 handleClick 함수를 실행시킨다

    handleKeyPressInput = (e) => {
        if (e.key === 'Enter') {
            this.handleClickBtn();
        }
    }

input 태그에 enter key 입력되면 댓글 추가되는 이벤트 추가

  • input 태그에 엔터키가 입려되면 댓글을 추가하기 위한 onKeyPress 이벤트를 추가해준다

  • 댓글 입력 태그에 글자가 입력되면 onKeyPress이벤트가 실행되므로,
    handleKeyPressInput 함수가 실행되는데 엔터키가 입력되면 조건에 만족하므로 true
    ture일때 블록의 내용인 입력받은 값을 배열에 저장하는 handelClickBtn 함수가 실행된다

<input 
  className="a-c-i-addtext" 
  type="text" 
  placeholder="댓글 달기..."
  onChange={this.handleChangeInput}
  onKeyPress={this.handleKeyPressInput}
/>

화면

엔터키 입력 구현 화면, console 결과

게시 버튼 클릭 구현 화면, console 결과


느낀점

아직 DOM의 이벤트랑 리액트의 이벤트거는 방식이 충돌해서 헷갈린다
그래도 초기 세팅은 DOM보다는 편한것 같다..아직 내가 못할뿐 ㅠㅠ
좀 더 열심히 다른 코드들을 봐야겠다. 많은 코드를 보면서 이해하는 것이 중요한 것 같다
왜 버튼을 클릭하면 map이 자동으로 실행되는지 아직 잘 모르겠다..
input 값을 추가한 배열을 넣어줘서 그런가? 거기에 값이 생성되서 근데 입력값이 없어도 게시버튼을 누르거나 엔터키를 입력하면 댓글이 추가되긴하는데,, 아 그건 내가 버튼을 눌러서 이벤트가 발생해서 그렇구나
많은 것들이 꼬여서 아직은 많이 헷갈린다
좀 더 많은 코드를 보면서 공부하면 나아지겠지

0개의 댓글