프로그래밍/React

React - 클래스 컴포넌트? state?

삐제제 2021. 8. 12. 04:14

 

 

 

 

컴포넌트는 두 가지 종류로 나누어진다.

 

Function 컴포넌트 / Class 컴포넌트 이 두 종류로 나뉘게 되는데,

 

생김새는 다음과 같다.

 

// Fucntion Component

function App() {
	return <h1>Hello i'm function component.><h1>
}

 

// Class Component

class App extends React.Component {
  render() {
    return <h1>Im a class component</h1>;
  }
}

 

각각 차이점을 비교하면,

 

Function 컴포넌트는 항상 무언가를 return 하여, screen에 표시한다.

 

Class 컴포넌트는 React.Component 를 반드시 상속받아야 한다! 

= App Component는 React.Component를 확장한다. (extends) => App Component는 React Component이다.

class React component는 return을 가지고 있지 않다. ( 클래스니까 )

대신 render()메서드를 가지고 있고, 이 메서드를 이용해서 screen에 표시한다.

그리고 React는 자동적으로 모든 클래스 컴포넌트의 render 메서드를 실행한다.

 

그런데 클래스 컴포넌트를 사용하는 이유는 무엇일까?

 

아마 여러가지가 있을 텐데 오늘 내가 공부한 내용으로는 state 때문이라고 한다.

state는 object이고, 컴포넌트는 데이터를 넣을 공간을 보유하고 있는데 이 데이터(state)는 변한다.

 

즉 바꾸고 싶은 데이터(변화를 주고 싶은 데이터?)를 state object에 선언하고, 이를 자바스크립트를 이용하여 변화시킬 수 있다.

 

class App extends React.Component {
  state = {
    count: 0,
  };
  add = () => {
    console.log("Add Button!");
  };
  minus = () => {
    console.log("Minus Button");
  };
  render() {
    return (
      <div>
        <h1>The number is : {this.state.count} </h1>
        <button onClick={this.add}>Add</button>
        <button onClick={this.minus}>Minus</button>
      </div>
    );
  }
}

export default App;

예시 코드인데, 이 코드에서는 count의 값이 변하거나 하진 않는다.

다만 App 클래스 컴포넌트 내부에, state오브젝트와 함수를 선언하고 그 함수를 어떻게 작동시키는지에 대한 예제이다.

버튼의 onClick은 리액트에서 button이 기본적으로 가지고 있는 prop이다.

위 코드의 결과

그러면 이제 안에 있는 값은 어떻게 변화를 시켜줘야 할까?

 

나는 처음에 이렇게 하면 되겠지라고 생각하였다.

class App extends React.Component {
  state = {
    count: 0,
  };
  add = () => {
    this.state.count++;
  };
  minus = () => {
    this.state.count--;
  };
  render() {
    return (
      <div>
        <h1>The number is : {this.state.count} </h1>
        <button onClick={this.add}>Add</button>
        <button onClick={this.minus}>Minus</button>
      </div>
    );
  }
}

export default App;

그런데 이렇게 하게 되면 VSC에디터에서 경고문을 출력한다.

"state를 직접적으로 변경하시면 안 됩니다, useState()를 사용하십시오. "

또, 실행시켜도 잘 동작하지 않는다.

 

그러면 안 되는 이유가 뭘까?

이렇게 하면 리액트는 render 함수를 refresh 않기 때문이라고 한다. 

 

그렇다면 setState()를 사용하면 어째서 동작하게 되는 걸까?

우리가 setState()를 사용하면 react가 우리가 언제 setState()를 호출할지를 알고, view를 refresh 하기를 원한다는 것도 알게 되고, render 함수도 refresh 하길 원하는 걸 알게 된다.

 

class App extends React.Component {
  state = {
    count: 0,
  };
  add = () => {
    this.setState({
      count: 1,
    });
  };
  minus = () => {
    this.setState({
      count: -1,
    });
  };
  render() {
    return (
      <div>
        <h1>The number is : {this.state.count} </h1>
        <button onClick={this.add}>Add</button>
        <button onClick={this.minus}>Minus</button>
      </div>
    );
  }
}

export default App;

setState 메서드는 첫 번째 인자로 state를 받고 state는 object이고, 새로운 state를 받아야 한다.

이렇게 수정하면 Add 버튼을 누르면 count는 1로 변하고, minus 버튼을 누르면 count는 -1로 변하게 된다.

즉 setState 메서드가 state를 (새로운 state와 함께) refresh 해주고, render 함수를 다시 호출해주는 것이다.

 

즉 누를 때마다 화면을 다시 칠한다는 건데,  리액트는 이런 작업을 할 때, virtual DOM을 사용하기 때문에 매우 빠르게 변경하고, 깜빡거리지도 않는 것이다.

 

setState 메서드를 사용하지 않으면, 새 state와 함께 render 함수는 호출되지 않을 것이다.

 

class App extends React.Component {
  state = {
    count: 0,
  };
  add = () => {
    this.setState({
      count: this.state.count + 1,
    });
  };
  minus = () => {
    this.setState({
      count: this.state.count - 1,
    });
  };
  render() {
    return (
      <div>
        <h1>The number is : {this.state.count} </h1>
        <button onClick={this.add}>Add</button>
        <button onClick={this.minus}>Minus</button>
      </div>
    );
  }
}

export default App;

코드를 이렇게 수정하면, Add 버튼을 누르면 값이 1씩 추가되고, Minus 버튼을 누르면 1씩 뺄셈이 된다.

 

그런데 위 코드처럼 state값을 변화시키는 건 좋은 방법이 아니라고 한다. (성능 문제를 유발할 수도 있고, 직접 state 값에 접근해서 변경하는 건 좋지 않다고 한다.)

 

대신에,

class App extends React.Component {
  state = {
    count: 0,
  };
  add = () => {
    this.setState((current) => ({ count: current.count + 1 }));
  };
  minus = () => {
    this.setState((current) => ({ count: current.count - 1 }));
  };
  render() {
    return (
      <div>
        <h1>The number is : {this.state.count} </h1>
        <button onClick={this.add}>Add</button>
        <button onClick={this.minus}>Minus</button>
      </div>
    );
  }
}

export default App;

이런 식으로 this.state 대신 current를 가져와서 state의 상태를 set 시키는 게 좋다고 한다.

그리고 이 방법이 state를 set 할 때 외부의 상태에 의존하지 않는 가장 좋은 방법이라고 한다.

 

 

* 번외로, setState메서드 안에서 호출된 arrow function에서 { count : current.count + 1 } 이 부분을 ()로 감싸준 이유가 무엇일까?

=>

화살표 함수를 통해 함수를 나타낸 경우 , () => {} 형식을 띄게 되는데,
뒤의 {} 부분이 return 할 대상으로 표현되는 경우가 많다고 한다.
만일 return 시에 객체를 반환할 경우(위와 같이)
js는 이게 return을 나타내기 위한 {} 인지, 아니면 객체를 나타내기 위한 {} 인지 잘 모르기 때문에 둘을 구분하기 위해 객체를 반환하는 경우에는 ({}) 를 사용한다고 한다. 

 

* 글을 받아 적고 곰곰이 생각을 해봤는데 arrow function은 뒤에 중괄호가 없으면 자동으로 값을 return 하는 특성을 가지고 있다. (중괄호 안에 코드를 작성하면 return으로 반환할 값을 명시했었다.)

예를 들면,

const foodController = (food) => food + 1;

이렇게 사용하면 return을 생략해도, 알아서 값을 return 하는 특징을 가지고 있었다.

this.setState((current) => ({ count: current.count + 1 }));

같은 원리인 것 같다 

 

 

this.setState( current => ({count: current.count -1 })); 

↕ (서로 같은 의미)

this.setState( current => {return current.count += 1});

 

 

* current가 뭔지 궁금해서 다른 이름으로 바꾸고 해 봤는데 똑같이 동작한다.

아마 setState 메서드의 구조 때문인 것 같다.

어렵구먼..

 

https://ko.reactjs.org/docs/faq-state.html

 

컴포넌트 State – React

A JavaScript library for building user interfaces

ko.reactjs.org

State에 대한 자세한 내용은 여기서 확인해봐야겠다.

 

'프로그래밍 > React' 카테고리의 다른 글

React - styled-components?  (0) 2021.08.19
React - CSS 모듈?  (0) 2021.08.19
React - 컴포넌트 Lift cycle  (0) 2021.08.15
React - PropTypes?  (0) 2021.08.10
React 공부 입성!  (0) 2021.08.10