본문 바로가기
🖊️Programming Language/📌React

[React] 이벤트

by 빛나고요 2021. 5. 5.
BIG

Study. React

이벤트

[이벤트 state props 그리고 render 함수]

📌이벤트는 props, state, 이벤트 이 세 가지가 서로 상호작용하며 애플리케이션의 역동성을 형성

 

📌WEB에 링크를 걸면 본문에 Welcome 메세지가 나옴

📌Subject를 클릭하면 그것에 해당하는 것들이 나옴

📌링크를 클릭하면 App컴포넌트에 state가 바뀌고 그 바뀐 state가 content 컴포넌트의 props 값으로 전달

📌mode: 사용자가 보고 있는 페이지가 Welcome페이지 인지 읽기 페이지 인지 구분

📌App.js

this.state = {
      mode:'welcome',
      subject:{title:'WEB', sub:'World Wide Web!'},
      welcom:{title:'Welcome', desc:'Hello, React!!'},
      // content 배열에 담겨있는 것을 TOC에 담음
      contents:[
        {id:1, title:'HTML', desc:'HTML is for information'},
        {id:2, title:'CSS', desc:'CSS is form design'},
        {id:3, title:'JavaScript', desc:'HTML is for interactive'}
      ],
      explain:{title:'HTML', desc:'HTML is Hypertext Markup Language.'}
    }

 

📌props값이나 state의 값이 바뀌면 그 state를 가지고 있는 컴포넌트의 render함수가 다시 호출됨 그래서 그 render함수 하위에 있는 컴포넌트들도 다시 호출됨

📌render(): 어떤 html을 그릴 것인지 나타냄, props값이나 state값이 바뀌면 render함수 하위의 컴포넌트들이 재호출 됨

📌mode의 값에 따라서 만들어지는 render함수의 결과가 달라지게 됨(welcome/read)

📌App.js

import React, { Component } from 'react';
import TOC from "./components/TOC";
import Content from "./components/Content";
import Subject from "./components/Subject";
import Aside from "./components/Aside";
import './App.css';

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      mode:'read',
      subject:{title:'WEB', sub:'World Wide Web!'},
      welcome:{title:'Welcome', desc:'Hello, React!!'},
      contents:[
        {id:1, title:'HTML', desc:'HTML is for information'},
        {id:2, title:'CSS', desc:'CSS is form design'},
        {id:3, title:'JavaScript', desc:'HTML is for interactive'}
      ],
      // explain:{title:'HTML', desc:'HTML is Hypertext Markup Language.'}
    }
  }
  render() {
    console.log('App render');
    var _title, _desc = null;
    if(this.state.mode === 'welcome'){
      _title = this.state.welcome.title;
      _desc = this.state.welcome.desc;
    } else if(this.state.mode === 'read'){
      _title = this.state.contents[0].title;
      _desc = this.state.contents[0].desc;
    }
    return (
      <div className="App">
        <Subject title={this.state.subject.title} 
        sub={this.state.subject.sub}>
        </Subject>
        <TOC data={this.state.contents}></TOC>
        <Content title={_title} desc={_desc}></Content>
        <Aside></Aside>
      </div>
    );
  }
}
export default App;

 

📌Content.js

import React, { Component } from 'react';

class Content extends Component{
    render(){
      console.log('Content render');
      return(
        <article>
          <h2>{this.props.title}</h2>
          {this.props.desc}
        </article>
      );
    }
  }
  export default Content;

 

📌mode가 welcome이 될 수도 있고 read가 될 수도 있는데, welcome이 되면 if문 안에서 welcome에 해당하는 부분이 실행돼서 state의 title과 desc를 바꾸고 read가 되면 if문 안에서 read에 해당하는 부분의 state가 실행

 

[이벤트 설치]

📌클릭 이벤트: onClick={} 

📌debugger: 크롬 개발자 도구를 켜 뒀을 때 코드의 debugger 라인에서 실행을 멈추고 Sources페이지로 이동하여 정보들을 쉽게 볼 수 있게 해 줌

📌코드를 실행하고 Sources 페이지로 가보면 debugger에서 실행을 멈춰있음

📌preventDefault(): 이벤트가 발생했을 때 기본적인 동작방법을 막음

📌App.js

import React, { Component } from 'react';
import TOC from "./components/TOC";
import Content from "./components/Content";
import Subject from "./components/Subject";
import Aside from "./components/Aside";
import './App.css';

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      mode:'read',
      subject:{title:'WEB', sub:'World Wide Web!'},
      welcome:{title:'Welcome', desc:'Hello, React!!'},
      contents:[
        {id:1, title:'HTML', desc:'HTML is for information'},
        {id:2, title:'CSS', desc:'CSS is form design'},
        {id:3, title:'JavaScript', desc:'HTML is for interactive'}
      ],
      // explain:{title:'HTML', desc:'HTML is Hypertext Markup Language.'}
    }
  }
  render() {
    console.log('App render');
    var _title, _desc = null;
    if(this.state.mode === 'welcome'){
      _title = this.state.welcome.title;
      _desc = this.state.welcome.desc;
    } else if(this.state.mode === 'read'){
      _title = this.state.contents[0].title;
      _desc = this.state.contents[0].desc;
    }
    return (
      <div className="App">
        {/* <Subject title={this.state.subject.title} 
        sub={this.state.subject.sub}>
        </Subject> */}
        <header>
            <h1><a href="/" onClick={function(e){
              console.log(e);
              e.preventDefault();
              debugger;
            }}>{this.state.subject.title}</a></h1>
            {this.state.subject.sub}
        </header>
        <TOC data={this.state.contents}></TOC>
        <Content title={_title} desc={_desc}></Content>
        {/* <Aside></Aside> */}
      </div>
    );
  }
  
}
export default App;

 

[이벤트에서 state 변경하기]

📌이벤트를 설치할 때 state를 찾을 수 없다고 하면 bind(this)를 함수가 끝난 직후에 추가해주면 됨

📌this.state.mode = 'welcome'; 을 써서 welcome 모드를 불러오고 React에게 mode가 welcome으로 바뀌었다는 것을 알리기 위해서 setState를 사용

📌App.js

return (
  <div className="App">
    {/* <Subject title={this.state.subject.title} 
    sub={this.state.subject.sub}>
    </Subject> */}
    <header>
      <h1><a href="/" onClick={function(e){
        console.log(e);
        e.preventDefault();
        this.state.mode = 'welcome';
        this.setState({
          mode: 'welcome'
        })
       }.bind(this)}>{this.state.subject.title}</a></h1>
       {this.state.subject.sub}
     </header>
     <TOC data={this.state.contents}></TOC>
     <Content title={_title} desc={_desc}></Content>
     {/* <Aside></Aside> */}
  </div>
);

 

[이벤트 bind 함수 이해하기]

📌bindTest() 함수를 호출했을 때 bindTest()의 this값을 obj로 넘겨줌

var obj = {name: 'student'};



function bindTest(){

  console.log(this.name);

}
bindTest(); 

📌bindTest();  를 해도 여기까지만 하면 실행이 안됨 왜냐하면 this가 obj가 될 이유가 없기 때문. 그래서 이유를 만들어주어야 함

 

📌bindTest.bind(obj);  : bind함수(이유)로 인해서 bindTest함수의 this는 obj가 됨. 그렇게 동작하는 새로운 함수(bindTest2)가 복제되어 만들어짐

var bindTest2 = bindTest.bind(obj);
bindTest2();

 

📌bind(this) : App이라는 컴포넌트 자체를 가리키는 객체를 function 안에서 this가 객체가 되도록 함.

{function(e){
              console.log(e);
              e.preventDefault();
              //this.state.mode = 'welcome';
              this.setState({
                mode: 'welcome'
              })
            }.bind(this)}

 

[이벤트 setState함수 이해하기]

📌state의 값을 직접 변경(this.state.mode = 'welcome';)하면 안 되고 함수를 이용해서 변경해야 함

📌이미 컴포넌트 생성이 끝난 다음에 동적으로 state값을 받고 있다면 setState함수에 변경하고 싶은 값을 객체 형태(this.setState({mode: 'welcome'});)로 넘겨주어야 함. 왜냐하면 React입장에서는 값을 직접 변경한다면 몰래 바꾼 셈이 되기 때문에 값이 바뀌었는지 몰라서 동작이 불가능

📌render함수 안에서는 state값이 바뀌면 setState로 바꿔주어야 하고 constructor함수에서는 값을 직접 변경해주면 됨

//this.state.mode = 'welcome';
this.setState({
	mode: 'welcome'
})

 

[컴포넌트 이벤트 만들기_1]

📌onChangePage함수 : 페이지가 바뀌었을 때 component 사용자가 설치한 함수를 호출, props로 전달

📌Subject.js

import React, { Component } from 'react';

class Subject extends Component {
    render() {
      console.log('Subject render');
      return (
        <header>
            <h1><a href="/" onClick={function(e){
              e.preventDefault();
              this.props.onChangePage();
            }.bind(this)}>{this.props.title}</a></h1>
            {this.props.sub}
        </header>
      );
    }
  }
export default Subject;

📌우리는 subject 컴포넌트에 onChangePage라고 하는 이벤트를 만들어서 함수를 입력하면 이벤트가 발생했을 때 props로 전달된 onChangePage라는 함수를 호출함

그렇게 해서 WEB을 누르면 Welcome  Hello, React!!로 바뀜

📌App.js

onChangePage={function(){
         this.setState({mode:'welcome'});
        }.bind(this)}

 

[컴포넌트 이벤트 만들기_2]

📌글 목록을 클릭했을 때 mode가 read로 바뀌고 WEB을 클릭하면 다시 mode가 Welcome으로 바뀌도록 함

📌App.js

<TOC 
          onChangePage={function(){
            this.setState({mode:'read'});
          }.bind(this)} 
        data={this.state.contents}
        >
        </TOC>

📌TOC.js

lists.push(
          <li key={data[i].id}>
            <a 
              href={"/content/"+data[i].id}
              onClick={function(e){
                e.preventDefault();
                this.props.onChangePage();
              }.bind(this)}
              >{data[i].title}</a></li>);
        i = i + 1;
      }

 

[컴포넌트 이벤트 만들기_3]

📌내가 클릭한 내용이 본문에 나타나게 하기

📌onClick 이벤트를 실행시킬 때 e.target.dataset.id 값을 이용해서 추출

 

 

💡이벤트가 발생했을 때 function(){}뒤에 .bind(this)를 붙이지 않으면 아래와 같은 에러가 표시된다. 

꼭 .bind(this)를 붙이자

그런데 문제가 생겼다. 내 파일에서는 HTML, CSS, JavaScript를 눌러도 내용이 바뀌지 않는다😮 

'🖊️Programming Language > 📌React' 카테고리의 다른 글

[React] Create 기능 구현  (0) 2021.05.07
[React] Props와 State  (0) 2021.05.06
[React] State  (0) 2021.05.04
[React] 컴포넌트 제작  (0) 2021.05.04
[React] 컴포넌트 제작  (0) 2021.05.03

댓글