함수형에 state를 쓸수있게된것은 최근의 이야기이고 그전에는 상태관리나 다른 기능들을 모두 클래스형을 썻기 때문에 아직도 예전에 만들어진 리액트코드들을 보면 클래스형 으로 만들어진것들이 있다고한다.
혹시라도 이것을 유지보수 할일이생긴다면 최소한 코드를 읽고 이해할수는 있어야하기에 과거의 유물도 배워야하는,..
(개발자 그들은대체...) 그래서 클래스 형을 공부해보려고 한다.
ClassComponent.js
import React, { Component } from 'react';
class ClassComponent extends Component{
render(){
return(
<div>
클래스형 컴포넌트 입니다
</div>
)
}
}
export default ClassComponent
우선 클래스형 컴포넌트는 이런 형식으로 작성하면된다. 위에 import하는부분에 컴포넌트라는것이 추가로 생겻고
함수형컴포넌트에서 함수를 만들어준것과 달리 클래스형 컴포넌트는 클래스를 만들면된다. (파일이름과같은)
정말 기본적인 형태만 가진 클래스형 컴포넌트이다. 클래스 형에서는 렌더메소드를 사용해서 JSX를 반환시켜준다.
App.js
import ClassComponent from './components/ClassComponent';
function App() {
return (
<ClassComponent/>
);
}
export default App;
app.js에서 import해서 사용하는 방법은 똑같이 사용하면된다.
클래스형 컴포넌트 Props사용
클래스형에서 props를 사용할때에는 this.props를 사용하면 app.js에서 보내준 props값을 조회할수있다
우선은 App.js에서 props값을 보내줘보겠다.
App.js
function App() {
return (
<ClassComponent color="blue" name="colazoa" isSpecial/>
);
}
{color : "blue" , name : "colazoa" isSpecial = {true} } 이런 객체의 형태로 props가 보내지고
ClassComponent.js
class ClassComponent extends Component{
render(){
const { color, name , isSpecial} = this.props
return(
<div style={{color}}>
클래스형 컴포넌트 입니다{isSpecial && "😒"}
<br/>안녕하세요 {name}
</div>
)
}
}
클래스 컴포넌트에서는 this.props로 값을 받아서 객체 구조분해 할당을 해주고 있다
(render메소드 안에서 해야함)
할당된 변수들을 넣어서 사용할수있다.
함수형과 똑같이 props에 default를 설정해줄수도 있다.
import React, { Component } from 'react';
class ClassComponent extends Component{
render(){
const { color, name , isSpecial} = this.props;
return(
<div style={{color}}>
클래스형 컴포넌트 입니다{isSpecial && "😒"};
<br/>안녕하세요 {name}
</div>
)
}
}
ClassComponent.defaultProps = {
name: '이름없음',
color: 'turquoise',
isSpecial:false
};
export default ClassComponent
요로케 넣어주면 App.js에서 props를 보내주지 않았을 때에는 default되있는 props값들이 적용된다.
아니면 클래스에서는 다른방법으로 static키워드를 사용해서 디폴트값을 설정할수도있다.
import React, { Component } from 'react';
class ClassComponent extends Component{
static defaultProps={
name: '이름없음',
color: 'turquoise',
isSpecial:false
}
render(){
const { color, name , isSpecial} = this.props;
return(
<div style={{color}}>
클래스형 컴포넌트 입니다{isSpecial && "😒"};
<br/>안녕하세요 {name}
</div>
)
}
}
// ClassComponent.defaultProps = {
// name: '이름없음',
// color: 'turquoise',
// isSpecial:false
// };
export default ClassComponent
밑의코드는 주석처리를 해주고 static 키워드를 이용해서 default 값을 줬다. 결과화면은 똑같이 나온다.
이렇게 전부사용이가능하다면 클래스형을 함수형으로 바꿀수도 있고
함수형을 클래스형으로 바꿔줄수도 있다.
저번에 만든 카운터컴포넌트를 클래스형 컴포넌트로 다시 만들어보겠다.
class ClassCounter extends Component{
render(){
return(
<div>
<h1>0</h1>
<button>+1</button>
<button>-1</button>
</div>
)
}
}
이렇게 클래스형으로 똑같이 만들어주고 이제 클래스형에서 상태값을 관리하는 방법을 알아보자!
class ClassCounter extends Component{
handleIncrease(){
console.log('increase')
console.log(this)
}
handleDecrease(){
console.log('decrease')
}
render(){
return(
<div>
<h1>0</h1>
<button onClick={this.handleIncrease}>+1</button>
<button onClick={this.handleDecrease}>-1</button>
</div>
)
}
}
함수형에서 안에 함수를 만들어줬던것처럼 클래스에서는 메서드를 만들어준다.(handleIncrease,handleDecrease)
이 상태에서는 함수에서 this키워드를 사용하면 undefined가 나온다
만든 메서드들을 각 button 들의 이벤트로 등록하게 되는 과정에서 각 메서드와 컴포넌트 인스턴스의
관계가 끊겨버리기 때문입니다.
그래서 이걸 다시 컴포넌트에 연결해주어야하는데
bind를 사용하는방법과 화살표함수를 사용하는 방법 2가지가있다.
bind를 사용해 this를 컴포넌트와 연결하는방법
class ClassCounter extends Component{
constructor(props){
super(props);
this.handleIncrease = this.handleIncrease.bind(this);
this.handleDecrease = this.handleDecrease.bind(this);
}
handleIncrease(){
console.log('increase')
}
handleDecrease(){
console.log('decrease')
}
render(){
return(
<div>
<h1>0</h1>
<button onClick={this.handleIncrease}>+1</button>
<button onClick={this.handleDecrease}>-1</button>
</div>
)
}
}
bind를 사용하면 this가 무엇을가리킬지를 직접 설정할수있다.
constructor 에서는 props 파라미터로 받아오고 super(props) 를 호출해주어야 하는데,
이는 이 클래스가 컴포넌트로서 작동 할 수 있도록 해주는 Component 쪽에 구현되어있는
생성자 함수를 먼저 실행해주고, 우리가 할 작업을 하겠다 라는 것을 의미합니다. (예..?)
class ClassCounter extends Component{
constructor(props){
super(props);
this.handleIncrease = this.handleIncrease.bind(this);
this.handleDecrease = this.handleDecrease.bind(this);
}
일단 클래스를 만들때Component라는 클래스에서 상속받아서 만드는거고..
생성자 함수constructor에 props가 들어가서 부모요소인 Component의 props를 받아오고
이제 만들어놓은 메서드들을 ClassCounter컴포넌트에 바인드한다...
(완전히 이해한건아닌것같고 이렇게까지는 맞는건가..)
화살표함수를 사용해 this를 컴포넌트에 연결하는방법
import React,{Component} from 'react'
class ClassCounter extends Component{
handleIncrease = () => {
console.log('increase')
console.log(this)
}
handleDecrease = () => {
console.log('decrease')
}
render(){
return(
<div>
<h1>0</h1>
<button onClick={this.handleIncrease}>+1</button>
<button onClick={this.handleDecrease}>-1</button>
</div>
)
}
}
export default ClassCounter
이렇게 메서드를 화살표함수로 만들어도 this를 받아올수있다.
아니면 그냥 onClick에서 함수를 만들어서 사용하는것도 가능하다.
render(){
return(
<div>
<h1>0</h1>
<button onClick={()=>{console.log("increase")
console.log(this)}}>+1</button>
<button onClick={()=>{console.log("decrease")
console.log(this)}}>-1</button>
</div>
)
}
이렇게도 사용이 가능은 한데 보기에도 별로고 렌더링할때마다 함수를새로만드는거기때문에
최적화도 힘들다고한다 추천하는 방법은 아닌것같다.
이제 메서드를 만드는방법들은 알았으니 상태값만있으면 된다.
상태값은 state를 선언해서 사용한다
state만들기 constructor로 만들때
constructor(props){
super(props)
this.state{
counter:0
};
}
이렇게 constructor안에 this,state로 상태값을 만들어주면 된다 클래스에서 state는 무조건 객체형태여야한다.
만들고 constructor안에 메서드도 bind연결 해주면된다.
화살표함수로 만들어서 생성자함수(constructor)를 쓰지않았다면.
state만들기 (화살표함수로 메서드를 만든경우)
stste={
counter : 0
}
그냥 이렇게 선언해줘도 문제없다.
이제여기서 상태값을 변경할때는 this.setState 를 사용해서 상태값을 변경해줄수있다.
ClassCounter.js
class ClassCounter extends Component{
state={
number:0
};
handleIncrease = () => {
this.setState({
number: this.state.number+1
});
};
handleDecrease = () => {
this.setState({
number: this.state.number-1
});
};
render(){
return(
<div>
<h1>{this.state.number}</h1>
<button onClick={this.handleIncrease}>+1</button>
<button onClick={this.handleDecrease}>-1</button>
</div>
)
}
}
this.setstate로 객체의 값을 변경시켜준다. state는 이 컴포넌트 안의 값이기때문에 바로 불러올수는없고 this키워드를 사용해서 this.state 그리고 키 값까지 써줘야 value 에 접근할수있다.
함수형업데이트
handleIncrease = () => {
this.setState(state=>({
number: state.number+1
}));
};
함수에서 this.setState를 이렇게 써주는걸 함수형 업데이트라고 한다.
이렇게 쓰면 this.setState를 여러번사용할수있는 장점이있다.
handleIncrease = () => {
this.setState(state=>({
number: state.number+1
}));
this.setState(state=>({
number: state.number+1
}));
};
이렇게 사용이 가능하고 클릭을했을 때 2씩 증가하게된다
그냥 this.setState로 사용했을 때는 값에 1을 더해주는 작업을 두번주지만,
실제로 2가 더해지지지는 않습니다.
업데이트 할 객체를 넣어주는 setState 에서 2씩 더해지지 않는 이유는 setState 를 한다고 해서 상태가 바로 바뀌는게 아니기 때문입니다. setState 는 단순히 상태를 바꾸는 함수가 아니라 상태로 바꿔달라고 요청해주는 함수로 이해를 해야합니다 (참고). 성능적인 이유 때문에 리액트에서는 상태가 바로 업데이트 되지 않고 비동기적으로 업데이트가 됩니다.
(벨로퍼트에서 알려주는 내용입니다. 자세한내용은 벨로퍼트에 가시면 보실수있습니다.)
(저도 보고하는거에요ㅠㅠㅜ)
여튼 이렇게 카운터를 클래스형으로 바꿔보았다 시작을 한지 얼마 안되었지만 벌써함수형이 눈에익은건지 함수형은 좀 알아먹을만 했던것같은데 클래스형은 복잡하다는 생각이든다 가능하면 마주치지말자우리...
혹시 만나더라도 못본척지나가주라...(애절)
'프론트엔드 정복기 > 리액트' 카테고리의 다른 글
[React] 7 JavaScript개념 정리(객체 Object) (0) | 2023.01.09 |
---|---|
[React]6 todolist만들기 (쉬운버전,어려운버전) (0) | 2023.01.08 |
[React] 4 input 상태 관리하기 (2) | 2023.01.08 |
[React]3 조건부렌더링,useState (2) | 2023.01.07 |
[React] 2 props로 컴포넌트에 값전달하기 (0) | 2023.01.07 |