리액트 컴포넌트에서 다루는 데이터는 두가지로 나뉜다.
state
props
props
는 나중에 배우겠지만, 미리 간단하게 설명하자면 props
는 부모 컴포넌트가 자식 컴포넌트에게 주는 값이다. 단방향성 특징을 가지고 있어, 자식 컴포넌트가 부모 컴포넌트에서 값을 줄 수 없고, 자식 컴포넌트는 props
를 받아오기만 할뿐, 받아온 props
는 직접 수정할 수 없다.
위에서 props
는 직접 수정할 수 없다고 이야기했다. 그렇다면 state
는 어떨까?
state
는 컴포넌트 내에서 값이 변할수 있다.
그렇기에 리액트에서 유동적인 데이터를 사용 할 때 state
를 사용한다. 단어 자체로 '상태'이고,
간단하게 정리하자면,
state
는 컴포넌트 내에 별도의 상태가 필요할 때 사용된다.
위에서 말로만 설명해도 직접 사용해보지 않는 이상 감이 오질 않는다. 이제 state
의 사용방법에 대해 알아보자.
state
는 해당 컴포넌트의 초기값이라고 보면 된다. 그래서 초기값 설정이 필수이며, 생성자(constrctor
)에서 this.state={}
로 설정한다.
(React.js 16.8부터 함수형 컴포넌트에서도 state를 사용할 수 있다.여기서는 class형 컴포넌트에 대해서만 설명하겠다.)
state
의 값을 변경할때 state
를 직접 조작해서는 안되며, 상태 변경이 필요할때는 setState
메소드를 이용해야 한다.
리액트는 state가 변경될 때마다 변경된 부분을 감지하여 리렌더링을 하는데 setState메소드를 사용하지 않고 직접 state 값을 수정할 경우 변경을 감지하지 못해서 리렌더링을 하지 못한다.
ex) this.state=...; ❌
컴포넌트의 생성자를 구현할 때는 super(props)를 선언을 권고한다.
이유는 this.props 사용 시 생성자 내에서 정의되지 않아 버그 발생 가능성이 생기기 때문이다.
리액트에서 컴포넌트를 생성할 때, state 값을 초기화, 메소드 바인딩할 때 constructor()
를 사용한다.
리액트의 컴포넌트의 생성자는 해당 컴포넌트가 마운트 되기 전 호출된다.
우리가 constructor
에서 super(props)
를 호출한 이유는, 우리가 컴포넌트를 만들게 되면서, React.Component를 상속했고, 우리가 이렇게 constructor
를 작성하게 되면 기존의 클래스 생성자를 덮어쓰게 된다.
그렇기에, 리액트 컴포넌트가 지니고있던 생성자를 super 를 통하여 미리 실행하고, 그 다음에 우리가 할 작업 (state 설정) 을 해주는 것이다.
*마운트:어떠한 것을 사용할 수 있는 상태로 준비하는 것
바인딩(Binding)- 프로그램의 어떤 기본 단위가 가질 수 있는 구성요소의 구체적인 값, 성격을 확정하는 것
constructor()
를 사용할때 흔히 많이 하는 실수로 setState를 호출한다.
생성자 내에서는 setState를 사용하는 것이 아닌 this.state로 초기값을 할당해주어야 한다.
생성자는 this.state를 직접 할당할 수 있는 곳으로 그 외에는 꼭 this.setState()를 사용하자.
생성자 내에서는 구독 작업이나 외부 API 호출을 하면 안 된다. 외부 API 호출이 필요하다면 componentDidMount()
를 사용 하도록 하자.
componentWillMount()를 사용하시던 분들이라면
componentDidMount()
로 함수를 수정해주세요. 현재 리액트에서 componentWillMount를 삭제 예정이므로 이제 이 함수를 사용하면 안돼요.
constructor
안에서 state값을 설정하는 것은 가능하고, 생성된 후 state값을 바꾸는 방법은setState
를 사용한다.
state를 변경하기 위해서는 setState()
메소드를 사용한다. 그리고 이 메소드는 비동기적으로 작동한다.
즉, setState()
함수를 사용해서 state를 업데이트 하더라도 즉시 반영되지 않는다는 뜻이다.
첫번째 인수 updater
함수로 전달된 state는 최신 값(기존의 값에서 변하게 만드려는 값)이다. 최신 값으로 상태를 업데이트 한다.
두번째 인수 callback
은 setState의 실행이 완료되고 컴포넌트가 렌더링 된 뒤에 실행될 함수이다.(생략가능하다.)
현재 state에서 age 속성을 1씩 증가시키는걸 확인할 수 있다.
또한, setState 함수에 첫번째 인수에 객체를 전달하여 state를 업데이트 할 수 있다.
첫번째 인수에 함수를 할당해 state를 업데이트 하는 동작과 동일한 결과를 나타낸다.
이제 render
함수에서 이벤트를 설정하는 방법에 대해 알아보자.
import React from "react";
class App extends React.Component{
constructor(props){
super(props);
this.state = {
name: 'sewon',
age:20,
hobby:'coding'
};
}
changeAgeHandler=()=>{
const {age} = this.state; //구조분해 할당
this.setState({age:age+1})
}
render() {
const{name,age,job} = this.state;
return (
<div>
<div>name:{name}</div> //name:sewon
<div onClick={this.changeAgeHandler}>age:{age}</div> //age:21
<div>hobby:{hobby}</div> // hobby:coding
</div>
);
}
}
export default App;
이벤트를 작성할때 알아야할 정보들이 있다.
camelCase
로 작성한다{this.changeAgeHandler}
또는 {(e)=> this.changeAgeHandler(e)}
로 작성하여야 한다.{this.changeAgeHandler}
로 작성이 가능한 이유는 {this.changeAgeHandler}
가 Arrow Function으로 작성되었기 때문에 bind(this)
를 사용할 필요가 없기 때문이다.