본문 바로가기
경일/React

[React] state, event, 조건에 따른 render

by dev_kong 2022. 4. 13.
728x90
728x90

0. 목차

1. 개요

2. state

3. event

4. 조건에 따른 render

1. 개요

어제에 이어서 react 기초 개념에 대한 내용이다.

state,event 그리고 ternary operator를 이용해 조건에 따른 render를 하는 방법에 대해 공부했다.

2. state

어제 공식문서를 보고 따라 쳐보긴 했지만 정확한 개념이 이해가 안돼서
state에 대한 내용을 정리하지 못했는데,
오늘 수업을 통해 state 와 조금 친해진 기분이다.

 

우선, state가 뭔지 정확하게 개념을 정리하는게 중요할 것 같다.

 

react 에서 state란, component 안에 저장 되어 있는 데이터이다.

 

어제 정리했던 props 와는 분명한 차이가 있다.
props는 부모 컴포넌트로 부터 자식 컴포넌트에게 전달되는 데이터인 반면에,

state는 해당 컴포넌트 자체적으로 저장되어있는 데이터이다.

그리고 react에서 가장 핵심이 되는 문장인

 

데이터가 변경되면 화면이 바뀐다.

 

라는 문장의 데이터state를 의미한다.

 

    class Test extends React.Component {
        state = { number: 1 };

        render() {
          return <div>{this.state.number}</div>;
        }
      }

      class App extends React.Component {
        render() {
          return (
            <div>
              <Test />
            </div>
          );
        }
      }

      const root = document.querySelector('#root');
      ReactDOM.render(<App />, root);

 

위의 코드를 보면,
Test 라는 컴포넌트 안에
state 라는 객체를 만들고 프로퍼티로 number:1 을 할당하였다.

그리고 render 를 통해 화면을 그리면
state 객체안의 key 가 number 인 value 1 이 화면에 찍힌다.

자바스크립트의 기본적인 class 사용법을 안다면,
조금 의아해 할 수 있는 코드이다.

 

state = {number:1};

 

이 부분이 조금 이상하다.

class 안에서 this없이 인스턴스 객체에 프로퍼티를 추가하는게 가능하던가?
원래라면 당연히 안된다.

그런데 React에서는 된다.
아마 extends 로 상속받는 React.Component 내부구조로 이뤄지는게 아닐까 싶다.

3. event

이번에는 state(상태)의 변화에 따라 화면이 달라지는 걸 해볼거다.

사용자가 어떤 행동을 취했을 때, state에 변화를 주는 것을 해볼건데,

버튼을 하나 만들고, 그 버튼이 클릭이 되면 현재 화면에 그려져있는 값에서
+1 을 하는 코드를 만들어 볼거다.

 

      class Test extends React.Component {
        state = { number: 1 };

        increaseNum = () => {
          this.setState({ number: this.state.number + 1 });
        };

        render() {
          return (
            <div>
              <button onClick={this.increaseNum}>더하기</button>
              {this.state.number}
            </div>
          );
        }
      }

 

Test 컴포넌트에 render 함수 리턴 값에 버튼을 하나 추가하고 onClick 으로 함수를 하나 달아줬다.

이부분에서 굉장히 주의 해야되는 게 하나 있는데,
return 이후 부분은 현)메타 구)페북 에서 만든 JSX 문법이다.


기냥 HTML 에서는 onclick 으로도 잘 작동 하지만
JSX 에서는 꼭 camelCase 를 이용해서 onClick 라고 해줘야만 정상적으로 동작한다.

 

그리고 increasNum 이라는 함수를 하나 메서드로 추가해서
이 함수가 동작할때 setState 라는 메서드가 동작하도록 만들었다.


이 setState 라는 메서드가 해당 컴포넌트의 state 를 변경해주는 역할을 한다.

그리고 이 setState 가 동작을 마치면 자동적으로 render 메서드가 동작한다.

 

현재 render 의 리턴값에 들어있는 div의 textContent 는 이 컴포넌트의 상태를 참조 하고 있기 때문에

setState 이후에 동작하는 render는 당연하게도 변경된 state를 참조하여 화면을 그릴것이다.

 

이렇게 만들어 놓고 나니

render는 함수선언문으로 increaseNum은 에로우펑션을 이용한 표현식으로 만들어 놓은게 좀 킹받는다.

increaseNum을 선언문으로 변경을 해봤더니

 

 

흠 이런 에러가 발생한다.

왤까...
한참을 고민 해보았는데,

increaseNum 함수가 일반함수로 호출돼서 그렇다.

 

함수가 일반함수로 호출되면 함수내부의 this는 전역객체에 binding 된다.

그래서 increaseNum 내부의 this.setState 는 window.setState로 동작을 하게되니
당연히 setState가 undefined 라고 오류가 발생한다.

 

어떻게 해결하면 될까.

우선은 위의 코드처럼 increaseNum을 에로우펑션을 이용해 선언하는 방법이 있고,

또는 onClick 이벤트에 실행되는 수를 에로우 펑션으로 감싸주는 방법이 있다.

 

 <button onClick={()=>{this.increaseNum()}}>더하기</button>

요렇게.

이게 왜 되누..? 라고 의문이 좀 드는데
에로우펑션에는 this binding 이 존재하지 않기때문에
this가 상위 스코프에 binding 된다.


해서 increaseNum 내부의 this가 인스턴스객체에 바인딩 되는 것이다.

그리고 또 한가지 방법은
increaseNum 에 bind 메서드를 이용하여 강제로 this binding 을 걸어 줄 수도 있다.

 

<button onClick={this.increaseNum.bind(this)}>더하기</button>

 

요렇게.

둘다 좀 생각을 해야되고, 얼핏 복잡해 보일 수도 있으니
그냥 메서드를 만들때 에로우펑션을 이용하는게 속편할지도 모르겠다.

그래도! 기왕이면 알고 쓰는게 낫지 않을까^^

 

4. 조건에 따른 render

이번에는 조금 다른걸 해보려 한다.

state에 따라서 화면에 render 되는 값을 다르게 찍어보려고 한다.

 

예를 들어서,
현재 위의 코드에서 state 의 number가 5보다 크면 5보다 큽니다! 라고 뜨게하고
5보다 작거나 같으면 5보다 작거나 같습니다! 라고 뜨게 해보는거다.

 

머릿속에 당연히
..ㅇㅇ if 문쓰면 되는거 아님..?
떠오른다.

 

   render() {
          return (
            <div>
              <button onClick={this.increaseNum.bind(this)}>더하기</button>
              {if(this.state.number > 5){
                '5보다 큽니다!'
              }else{
                '5보다 작습니다!'
              }}
            </div>
          );
        }

이렇게

근데 안된다.
return 이후에는 JSX 문법이 사용된다.
근데 JSX 문법에는 if가 없다..!


왤까?
모른다
마크형 한테 DM을 날려보면 알려줄지도 모르겠다.

 

그럼 어케하누..

JSX 문법에서는 모든 if문이 ternary operator(삼항연산자)로 대체되어 사용된다.
만든사람이 그렇게 만들어 놓은 거니까
왜..? 라는 의문은 잠시 접어두고 시키는대로 한번 해보자.

 

        render() {
          return (
            <div>
              <button onClick={this.increaseNum.bind(this)}>더하기</button>
              number : {this.state.number}
              <div>
                {this.state.number > 5
                  ? 'number가 5보다 큽니다!'
                  : 'number가 5보다 작거나 같습니다'}
              </div>
            </div>
          );
        }

 

이렇게 하면 된다.. ㅎ

 

리액트 아직까지는 좀 재밌는거 같다.

 

전체 코드는 Github에 있음.

728x90
728x90

댓글