컴포넌트 이벤트 만들기(2)

SPANKEEE·2022년 12월 26일
0

리액트-시작

목록 보기
18/30

이번에는 글 목록을 클릭했을 때 <App>컴포넌트의 state모드("mode")"read"로 바꾸고 클릭한 글 목록에 해당하는 contents 내용이 본문에 나오도록 만들어 보자.

이벤트 더 만들어 보기

<Navi>컴포넌트에 onChangePage와 똑같은 이름의 경고창을 보여주는 이벤트를 만들어보자.

onChangePage

onChangePage={function(){
  alert('Hello!');
}.bind(this)}

이렇게 생성한onChangePage이벤트 <Navi>컴포넌트 안에서 props형태로 전달받을 수 있다.

<Navi> 컴포넌트 render내부

var lists = []; // 리스트 배열
var data = this.props.data; /*
<App>컴포넌트로 가서 Navi를 확인하면
var data = this.state.contents[i]; 로 되어있으므로
this.props.data가 컴포넌트 프롭스(props)를 통해 값을 가져온다.*/
var i = 0;
while(i <data.lenght){
  lists.push(
  	<li key = {data[i].id}>
    <a href={"/content/" + data[i].id}
    	onClick={function(e){
      	e.preventDefault();
      	this.props.onChange();
    }.bind(this)}>{data[i].title}</a>
  	</li>);

<Navi>컴포넌트 안에 각각 목록에 해당하는 <li>부분에 링크를 클릭했을 때 onClick 이벤트가 실행된다.
이벤트가 실행될 때 페이지가 바뀌지 않도록 e.preventDefault() 함수를 추가해준다.
this.props.onChangePage();라고 props속성 형태로 onChangePage()함수를 실행시켜 정상적으로 작동하게 된다.

  • 작동 확인

이벤트가 정상적으로 작동되는 것을 확인했다.
이제 App.js파일로 들어가서
<Navi>컴포넌트 props에 정의되어있는 onChangePage함수를 수정해
<App>컴포넌트의 state "mode"의 값을 "read"로 바꾸도록 코드를 수정해보자.

App.js > <Navi> > props

onChange = {function(){
  this.setState({mode:'read'});
}.bind(this)}
  • 결과화면

이제 링크를 mode라는 state가 변하는 것을 확인할 수 있다.


리스트 선택시 본문에 텍스트 표시하기

이번엔 글 목록에 선택한 content가 본문에 표시되도록 해보자.
여기서부턴 이벤트가 중심보다는 state에 집중을 하도록 한다.

<App>컴포넌트의 state에 selected_content_id와 같은 이름으로 우리가 현재 선택한 content를 표시할 것이다.

그 값을 바탕으로 contents라고 하는 객체에 있는 id 값과 일치하는 selected_content_id 값과 일치하는 것을 본문에 표시할 것이다.

App.js > App > constructor > contents

this.state = {
  mode: 'read',
  selected_content_id: 2,
  welcome: { title: 'welcome', desc: 'Hello, React!!' },
  subject: { title: 'SAMPLETITLE', sub: 'this is sub text!' },
  artsub: { title: "NEW ARTICLE", sub: "this Arti has been updated" },
  contents: [
    { id: 1, title: 'Alpha', desc: 'this area is Section_alpha!' },
    { id: 2, title: 'Delta', desc: 'this area is Section_delta!' },
    { id: 3, title: 'Charlie', desc: 'this area is Section_charlie!' },
  ]
}

위 코드처럼 App 컴포넌트의 state에 selected_content_id를 2로 설정함으로써 기본적으로 2번 content가 선택되게 한다.
mode가 read일 때 selected_content_id의 값에 따라 content 배열 중 무엇이 본문에 나올 것인지를 지정하도록 한다.

App.js > App > render

// 렌더 실행할때 state mode가 read일 경우
else if(this.state.mode === 'read'){
  _title = this.state.contents[0].title; // id : 1인 Alpha 타이틀
  _desc = this.state.contents[0].desc; // id : 1인 Delta 타이틀
  /* selected_content_id 활용구간 */
  var i = 0; // 인덱스
  while(i < this.state.contents.length){ // state콘텐츠 길이만큼 반복
    var data = this.state.contents[i]; // data는 state의 content[i]번째 가져옴
    if(data.id === this.state.selected_content_id){ // id값과 selected_content_id 일치하면?
      _title = data.title; // data의 title
      _desc = data.desc;   // data의 desc
      break; // 루프 탈출
    }
    i = i + 1; // 위 if문 만족하지 않을경우 인덱스 i 1 증가
  }
}

위 코드처럼 반복문을 수행하며 현재 순번에 해당하는 contents의 data.id 값과 this.state.selected_content_id 값이 일차하는 경우 _title, _desc에 해당된다.

이처럼 변경시 selected_content_id가 2번이므로 2번에 해당되는 Delta content가 본문에 표시된다.

이를 이용하여 <Navi>컴포넌트 listonChangePage이벤트가 발생했을 때 this.setState를 이용하여 mode값과 함께 selected_content_id의 값을 변경하면 된다.

App.js > App > render > Navi.props

<Navi
  onChangePage={function (id) {
    this.setState({
      mode: 'read',
      selected_content_id: ..?
    });
  }.bind(this)}
  data={this.state.contents}
</Navi>

<Navi>컴포넌트의 onChangePage이벤트를 실행시키는 부분은 Navi.js에서 a 태그의 onclick이벤트가 발생했을 때
this.props.onChangePage()를 실행 시 App.js에 있는 onChangePage함수를 실행시키면 된다.

onChangePage() 함수를 실행시킬 때 항목의 id 값을 넘기도록 구현해보자.

Navi.js > render

var lists = [];
var data = this.props.data;
var i = 0;
while (i < data.length) {
  lists.push(
    <li key={data[i].id}>
      <a href={"/content/" + data[i].id}
        data-id={data[i].id} // "data-" 로 시작되는 접두사를 붙이면?
        //dataset이라고 하는 특수한 형태에서 접근할 수 있다.
        onClick={function (e) {
          debugger; // e 구간 체크하기
          e.preventDefault(); // 페이지 이동 해제
          this.props.onChangePage(); // 사용자 이벤트 호출
        }.bind(this)}>
          {data[i].title}
      </a>
    </li>);
  i = i + 1;
}

<Navi>컴포넌트의 a태그에 "data-i = {data[i].id}"와 같은 속성을 주고 로드하면 해당하는 id 값인 1,2,3 을 확인할 수 있다.

Navi안에 있는 a태그의 props --> data-id 확인

그리고 디버거로 잠시 실행을 멈추고 onClick발동시 e 라는 이벤트 객체는 어떤정보가 들어가 있는지 확인해보자.

이벤트 객체 e 체크

  • 콘솔에 e를 입력하고 엔터를 친다.

위에 target이라는 속성은 이벤트가 발생한 태그를 가리킨다.
이를 통해 a태그를 알아내고 a태그가 가지고 있는 data-id 값에 접근할 수 있다. (속성값 접근)
"data-"로 시작되는 속성은 dataset이라고 하는 특수한 형태에서 접근할 수 있다.

위에서 사용한 속성은 data-id이므로 접미사는 id에 해당된다.

e객체의 target 속성에서 dataset의 해당하는 값이 data-id의 값이 된다.
이렇게 알아낸 정보를 onChangePage()함수를 호출하는 코드에 인자로 넣으면 된다.

Navi.js > render

var lists = []; var data = this.props.data; var i = 0;
while...생략
<li key={data[i].id}>
  <a href={"/content/" + data[i].id}
    data-id={data[i].id} // "data-" 로 시작되는 접두사를 붙이면?
   //dataset이라고 하는 특수한 형태에서 접근할 수 있다.
    onClick={function (e) {
      e.preventDefault(); // 페이지 이동 해제
      this.props.onChangePage(e.target.dataset.id); // 사용자 이벤트 호출
      // 이벤트객체가 가르킨 a태그 속성중 접두사 data-가 있는 data-id의 정보를 얻음
    }.bind(this)}>{data[i].title}
  </a>
</li>

onChangePage 에 id 라는 매개변수를 주고 이 id 값을 selected_contnet_id의 값으로 넣어준다.
이때 넘어오는 데이터는 문자니까 contentid는 숫자이므로 Number()를 사용하여 문자를 숫자로 바꿔준다.

App.js > Navi 컴포넌트

<Navi
  onChangePage={function (id) { 
    // id는 Navi.js가 해당 함수를 호출하고 e객체가 가진 데이터를 사용
    this.setState({
      mode: 'read',
      selected_content_id: Number(id)
    });
  }.bind(this)}
  data={this.state.contents}
</Navi>

위 코드를 작성하고 실행하면

  • SAMPLETITLE을 클릭 시 ==> 모드(mode)가 welcome으로 바뀌고
  • Navi의 a 태그를 클릭 시 ==> 모드(mode)가 read으로 바뀌고 클릭한 목록에 해당되는 selected_content_id가 바뀌어 본문의 내용도 바뀌는 것을 확인할 수 있다.

속성을 이용하지 않고 하는 방법

bind(this)의 두번째 인자로 data[i].id 값을 주면 onClick 이벤트에서 실행되는 함수의
첫번째 매개변수 값bind의 두번째 인자로 불러온 값인 data[i].id가 된다.

Navi.js > render

  • 속성 이용 안하는 방법
<li key={data[i].id}>
  <a href={"/content/" + data[i].id}
    // data-id={data[i].id} // 속성이 정말 활용안되는지 주석처리
    onClick={function (id,e) {
      e.preventDefault(); // 페이지 이동 해제
      this.props.onChangePage(id); // 사용자 이벤트 호출
    }.bind(this, data[i].id)}>{data[i].title}
  </a>
</li>

위 처럼 a태그 내에 data-id라는 속성이 없어도 원하는 결과가 나오는 것을 확인할 수 있다.


Navi의 a태그 onClick시 매개변수 정리

  • function(e) -> e 객체가 가르키는 태그의 속성을 dataset.id로 조회해서 보낼경우, 함수 끝날 때 bind(this)로 입력
  • function(id, e) -> 인자로 이벤트객체 e 와 id를 사용하며 e는 위 그대로 사용,
    인자 id는 해당 태그가 만들어낼때 id값을 가지고 있음
    이때 this.props.이벤트 발생시 인자를 e가 아닌 id를 입력한다.
    함수가 끝날 때 (this, data[i].id]) 입력
profile
해야되요

0개의 댓글