리액트의 처음과 끝은 컴포넌트라고 말할 수 있습니다. 컴포넌트의 종류에는 많은 종류가 있지만 그 중에서 우리는 클래스형 컴포넌트에서 state를 정의하는 두 가지 방법에 대해 알아보도록 하겠습니다.
함수형 컴포넌트에서 Hooks를 통해 state를 정의할 수 있는 것처럼, 다른 종류의 컴포넌트에서도 충분히 state를 정의하고 사용할 수 있지만 본 포스트에서는 다루지 않으니 참고바랍니다.
클래스는 자바스크립트 ES6에 등장한 개념입니다. 생성자는 클래스의 인스턴스가 생성되면 가장 먼저 실행되는 메소드입니다. '생성자'라는 이름에 걸맞게 클래스의 다른 어떤 메소드보다 먼저 실행되며, 주로 인스턴스의 초기 설정에 대한 로직을 생성자에 작성합니다.
아래의 코드는 Person 클래스의 인스턴스를 생성했을 때 어떤 일이 일어나는지 나타냅니다.
import React, { Component } from 'react';
class Person extends Component {
constructor(props) {
super(props);
console.log('Person Instance is created, and initialized');
}
render() {
return <div>Hello World!</div>;
}
}
export default Person;
이 코드를 import하여 실행시키면 생성자에 작성한 문구가 콘솔에 찍히는 것을 볼 수 있습니다.
생성자에 적힌 super(props);
는 반드시 생성자의 최상단에 작성해야합니다.
이에 대한 자세한 이유는 이곳이 잘 정리하였으니 참고해주세요.
state는 컴포넌트의 렌더링 결과물에 영향을 주는 정보를 저장한 일종의 자바스크립트 객체입니다. state는 컴포넌트 안에서 관리되며, 컴포넌트는 state의 값이 바뀔 때 마다 화면을 다시 렌더링합니다. state의 값을 바꾸는 방법은 this.state
와 this.setState
두 가지가 있습니다. this.state
는 주로 생성자 안에서 state를 초기화할 때 사용하고, this.setState
는 나머지 상황에서 사용합니다.
constructor(props) {
super(props);
this.state = {name: 'Cada'}; // 첫번째 방법
}
setName(name) {
this.setState({name: name}); // 두번째 방법
}
state를 정의하는 한 가지 방법은 생성자 안에서 state를 정의하는 것입니다. 생성자는 위에서 언급한 것처럼 클래스 인스턴스가 생성될 때, 그리고 컴포넌트가 렌더링이 되기 전에 가장 먼저 실행되는 메소드입니다. 따라서 state의 기본값을 정의하는 방법으로 생성자를 이용하는 것이 가장 완벽한 방법일 것입니다.
아래의 코드는 Person 컴포넌트의 state를 생성자 안에서 지정하여 화면에 보여주는 예시입니다.
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: 'Cada',
age: 25,
country: 'KR'
}
}
render() {
return <div>{this.state.name} {this.state.age} {this.state.country}</div>;
}
}
export default App;
state를 정의하는 다른 방법은 생성자 밖에서 state를 정의하는 것입니다. 클래스 인스턴스가 생성될 때, 클래스의 모든 속성도 함께 생성됩니다. 따라서 우리는 state 속성을 렌더링 단계에서 사용할 수 있습니다.
아래의 예시는 생성자 안에서 state를 정의한 것과 동일한 결과를 보여줍니다.
import React, { Component } from 'react';
class App extends Component {
this.state = {
name: 'Cada',
age: 25,
country: 'KR'
}
render() {
return <div>{this.state.name} {this.state.age} {this.state.country}</div>;
}
}
export default App;
두 가지 방법은 사실상 동일합니다. 어떤 것을 사용하냐는 개인의 선택의 문제이고 성능상의 차이는 없습니다. 차이에 대해 조금 더 상세하게 확인하고 싶다면 이곳에 들어가 아래의 코드를 입력해보세요.
// Without constructor
class WithoutConstructor {
state = {
name: "Bhargav"
}
}
// With constructor
class WithConstructor {
constructor() {
this.state = {
name: "Bhargav"
}
}
}
페이지의 왼쪽에 코드를 입력하면 오른쪽에 내부적으로 어떤 구조가 생성되었는지 확인할 수 있습니다. 거의 동일한 구조를 보여주지만 생성자 밖에서 클래스 속성을 이용하여 state를 지정한 코드는 defineproperty
로 state를 정의하는 것을 볼 수 있습니다. 객체의 속성을 직접 조작하는 것이죠.
어떤 방법을 선택해도 여러분들이 작성한 코드의 결과물에는 차이가 없습니다.
자신의 입맛에 맞게 선택해 사용하면 됩니다.