[리액트] function과 class / props와 state
토이 프로젝트에서 몬스터 생성과 이동을 맡았다. 몬스터를 만들면서 내가 개인적으로 function과 class, props와 state에 대해 어떻게 이해했는지 작성해보려고 한다.
몬스터에게 필요한것은 위치, 크기, 속도, 이동방향, 이미지 등이 있을 것이다.
먼저 MonsterInstance Class를 생성했다.
그 안에서 몬스터 정보를 받도록 했다..
// Monster.js
class MonsterInstance extends React.Component {
constructor(props) {
super(props);
this.state = {
position: props.position,
scale: props.scale,
visible: true,
img: props.img,
dir: 1,
}
}
리액트에서 constructor는 생성자임.
props는 어디서 받아오냐면 바로바로 Monster.js 상위의 js인
// attack.js
// 코드는 필요한 부분만 요약했습니다.
import { useState, useSyncExternalStore } from "react";
import Monster from "./Monster";
const Panel = (props) => {
const [monster, setMonster] = useState([
{
id: 1,
position: {
x: 0,
y: 0,
},
scale: {
x: 50,
y: 50,
},
visible: true,
img: require("../../img/monster.gif"),
},
{
id: 2,
position: {
x: 400,
y: 500,
},
scale: {
x: 50,
y: 50,
},
visible: true,
img: require("../../img/monster.gif"),
},
{
id: 3,
position: {
x: 700,
y: 20,
},
scale: {
x: 50,
y: 50,
},
visible: true,
img: require("../../img/monster.gif"),
},
{
id: 4,
position: {
x: 600,
y: 560,
},
scale: {
x: 50,
y: 50,
},
visible: true,
img: require("../../img/monster.gif"),
},
]);
return (
<Container>
{monster.map((item, index) =>
<Monster key={index} id={item.id}
position={item.position} scale={item.scale}
img={item.img} />
)}
</Container>
)
};
export default Panel;
attack.js 가장 하단에서 필요한 정보를 넘긴다. monster 배열에서 4개를 선언했기때문에 4마리의 몬스터가 생길것이다.
다시 Monster.js로 돌아와서
// Monster.js
import React from "react";
class MonsterInstance extends React.Component {
constructor(props) {
super(props);
this.state = {
position: props.position,
scale: props.scale,
visible: true,
img: props.img,
dir: 1,
}
}
componentDidMount() {
this.position = setInterval(
() => this.move(),
500
);
}
move() {
if (this.state.position.x < 0) {
this.setState({dir: -1})
}
if (this.state.position.x > 1024) {
this.setState({dir: 1})
}
this.setState({
position: {
x: this.state.position.x - (10*this.state.dir),
y: this.state.position.y
}
})
}
render() {
return(
<div>
<Monster key={this.props.index} id={this.props.id}
position={this.state.position} scale={this.state.scale} img={this.state.img}/>
</div>
);
}
}
export default MonsterInstance;
attack.js에서 받아온 props 정보를 state에 대입하고,
componentDidMount() : component mount 가 되면 실행 됨. setInterval을 통해 move() 함수를 실행하도록했다.
몬스터가 영역내에서 좌우로 움직이도록 move() 함수 작성.
render 영역에서 몬스터를 불러온다. 몬스터 정보를 Monster에 넘긴다.
Monster는 다음과 같이 작성했다.
// Monster.js
function Monster(props) {
return (
<div>
<img className=""
style={{left: props.position.x, top: props.position.y,
width: props.scale.x, height: props.scale.y,
position: "absolute",
zIndex: 2,
}}
key={props.index} id={props.id}
alt="monster" src={props.img}/>
</div>
);
}
MonsterInstance에서 Monster을 불러옴!!
여기서 function이라고 선언한 것과 class라고 선언한 것의 차이점이 있는데
function은 constructor 을 선언할 수 없다..
function은 렌더링된 값들을 고정시킨다.
Monster 정보를 받아와서 고정시켜 고대로 뿌리겠다는 것이다..!
class는 React.Component를 extends 하고, constructor을 쓸 수 있음..
그리고 위 코드 예제를 보시다시피
클래스 컴포넌트는 componentDidMount, getDerivedStateFromProps 등 React Component의 라이프사이클을 사용할 수 있다. 반면에 함수형은 이런것을 쓸 수 없고 render만 구현가능하다..!
props는 다른 곳에서 전달 받은 정보를 가져오는 것이고
state는 class 컴포넌트 내에서 생성자 처럼 쓸 수 있는 개념..!
그래서 move() 함수내에서 this.setState를 통해 값을 변경해서 몬스터가 움직이게 할 수 있는 것이다.~
뭐라고 쓰고 있는지 모르겠다.. 주말에 글을 깔끔하게 정리해야겠다.