props와 state는 react에서 데이터를 다룰 때 사용된다.
부모 컴포넌트가 자식컴포넌트한테 값을 전달할 때 사용된다.
<chile value="value">
에서 value가 하나의 props이다.
과정1. 새로운 컴포넌트 만들기
MyName.js
import React, {Component} from 'react';
class MyName ectends Component {
render() {
return (
<div>안녕하세요 제 이름은 <b>this.props.name</b>입니다 </div>
)
}
}
export default MyName;
App.js
import React, {Component} from 'react';
import Myname from './Myname';
class App extends Component {
render() {
return <Myname name="리액트"/>
}
}
이렇게 하면 Myname을 실행시켰을 때
안녕하세요 제 이름은 리액트입니다.
라고 뜬다.
만약 부모 컴포넌트인 App.js에서 실수로 props부분을 빠뜨리고
return <Myname />
이런식으로 종료하게 될 때를 대비해서 Myname에서 default 값을 지정해줘야한다.
첫 번째 방법
MyName.js
import React, {Component} from 'react';
class MyName ectends Component {
static defaultProps = {
name: '기본이름'
}
render() {
return (
<div>안녕하세요 제 이름은 <b>this.props.name</b>입니다 </div>
)
}
}
export defualt MyName;
두 번째 방법
MyName.js
import React, {Component} from 'react';
class MyName ectends Component {
render() {
return (
<div>안녕하세요 제 이름은 <b>this.props.name</b>입니다 </div>
)
}
}
MyName.defaultProps = {
name: '지원이'
};
export defualt MyName;
첫번째 방법과 두번째 방법은 완전 같은 역할을 하지만 첫번째 방법이 최신 자바스크립트 문법을 반영한 것이다.
컴퓨넌트를 만들 때 위의 방법처럼 class를 사용해서 만드는 것 말고 함수형컴포넌트라는 방법이 있다.
함수형 컴포넌트는 단순히 props만 받아와서 보여주는 경우이다.
딱히 기능을 추가하지 않고 위처럼 그냥 보여지는 것만 컨트롤 할 경우는 함수형 컴포넌트를 많이 사용하다.
함수형 컴포넌트 작성
import React from 'react';
const MyName = ({name}) => {
return (
<div>안녕하세요! 제 이름은 {name}입니다.</div>
)
};
MyName.defaultProps = {
name: '지원이'
}
함수형 컴포넌트를 사용하면 더이상 코드의 상단에서 컴포넌트를 불러오지 않아도 된다.
코드 내부에 react를 사용하는 부분이 없다고 하더라도 jsx가 만들어질 때 react를 사용하기 때문에 적어줘야한다.
함수형 컴포넌트와 class형 컴포넌트의 차이점은 state라는 기능의 유무와 lifecycle도 없다.
함수형 컴포넌트는 메모리 자원도 덜 사용하고 초기 속도가 더 빠르다. 그래서 컴포넌트 생성 시 단순히 값을 받아와서 보여지게하는 구조라면 class형보다 함수형 컴포넌트를 사용해줘야 성능을 향상시킬 수 있다.
앞전의 props는 부모가 컴포넌트를 렌더링할 때 특정 값을 자식에게 설정해주는 방식으로 내려주는 값이고 자식입장에서 props는 읽기 전용이다.
이와 달리 state 는 부모와 관계 없이 컴포넌트 자기 자신이 가지고 있는 값이다. 만약 변화가 필요하면 컴포넌트의 내장함수 중 하나인 setState()
를 통해 값을 설정해준다.
Counter.js
import React, {Component} from 'react';
class Counter extends Component {
render() {
return (
<div>
<h1>카운터</h1>
<div>값: 0</div>
<button>+</button>
<button>-</button>
</div>
);
}
}
ecport default Counter;
Counter를 App에서 렌더링 해줘볼 것이다.
App.js
import Recat {Component} from 'recat';
import Counter from './Counter';
lass App extends Component {
render() {
return <Counter />;
}
}
export default App;
이 상태로 작동을 시키면 아무 변화가 없다.
일단 버튼을 눌렀을 때 '값'의 숫자가 눌리는 버튼에 맞게 카운팅 되도록 구현해 줄 것이다.
우선 버튼이 눌릴 때 마다 Counter.js를 리렌더해줘야한다.
그것을 구현해 볼 것이다.
Counter.js
import React, {Component} from 'react';
class Counter extends Component {
state = {
number: 0
}
render() {
return (
<div>
<h1>카운터</h1>
<div>값: {this.state.number}</div>
<button>+</button>
<button>-</button>
</div>
);
}
}
ecport default Counter;
이 상태에서는 값에 state라는 object의 number값이 들어가긴 하지만 그 값을 변경시켜주는 코드를 추가해줘야한다.
import React, {Component} from 'react';
class Counter 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>카운터</h1>
<div>값: {this.state.number}</div>
<button>+</button>
<button>-</button>
</div>
);
}
}
ecport default Counter;
위 코드 중 this.setState({어쩌구})
이 부분을 this.state.number = this.state.number+1로 바로 설정해주면 컴포넌트가 state값의 업데이트여부를 알 수 없게되므로 위와 같은 방식으로 해줘야햔다.
import React, {Component} from 'react';
class Counter 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>카운터</h1>
<div>값: {this.state.number}</div>
<button onclick={this.handleIncrease}>+</button>
<button onclick={this.handleDerease}>-</button>
</div>
);
}
}
ecport default Counter;
(?)왜 render함수는 일반함수로 쓰고 hadleIncrease(Decrease)함수는 화살표함수를 썼을까?
만약 handle.. 함수를 일반함수로 만들면 handle..함수 내에서 this라는 키워드를 알지 못한다. 이것을 해결하기 위해서는 constructor
라는 컴포넌트가 생성될 때 만들어지는 함수를 호출해줘야한다.
Counter.js
import React, {Component} from 'react';
class Counter extends Component {
state = {
number: 0,
}
constructor(props) {
super(props);
this.handleIncrease = this.handleIncrease.bind(this);
this.handleDecrease = this.handleDecrease.bind(this);
}
handleIncrease(){
this.setState({
number: this.state.number + 1
})
}
handleDecrease() {
this.setState({
number: this.state.number - 1
})
}
render() {
return (
<div>
<h1>카운터</h1>
<div>값: {this.state.number}</div>
<button onclick={this.handleIncrease}>+</button>
<button onclick={this.handleDerease}>-</button>
</div>
);
}
}
ecport default Counter;
위처럼 constructor함수를 추가해줘야지 handle.. 함수에서 사용하는 this가 constructor에서 사용하는 this임을 명시가 된다.
즉 props는 읽기만 가능하고 state는 변경도 가능하다는 점의 큰 차이가 있다.