리액트에서 컴포넌트는 함수형 컴포넌트와, 클래스형 컴포넌트로 나눌 수 있다.
- 클래스형 컴포넌트에서는 state 기능, 라이프사이클 API 기능을 사용할 수 있습니다.
- 함수형에서는 state와 라이프사이클 AP를 사용할 수 없습니다. 하지만 Hooks라는 기능이 도입되면서 해결되었습니다.
● 함수형 컴포넌트, props, propTypes
import "./App.css";
function App() {
return <div>안녕하세요? 함수형 컴포넌트 입니다.</div>;
}
export default App;
props는 아래와 같이 적어줍니다.
App.js
import MyComponent from "./MyComponent";
function App() {
return (
<div>
안녕하세요? 함수형 컴포넌트 입니다.
<MyComponent name={"daeun"} />
</div>
);
}
export default App;
props로 자식 컴포넌트에 name을 전달해주어야합니다.
MyComponent.js
const MyComponent = (props) => {
return <div>{props.name}</div>;
};
export default MyComponent;
디스트럭처링 구조로 props를 전달 받을 수도 있습니다.
const MyComponent = ({ name }) => {
return <div>{name}</div>;
};
export default MyComponent;
props의 기본 설정 값과, 타입을 결정할 수도 있습니다.
App.js에서는 props를 전달하지 않습니다.
App.js
import MyComponent from "./MyComponent";
function App() {
return (
<div>
안녕하세요? 함수형 컴포넌트 입니다.
<MyComponent />
</div>
);
}
MyComponent.js
const MyComponent = ({ name }) => {
return <div>{name}</div>;
};
MyComponent.defaultProps = {
name: "김다은",
};
export default MyComponent;
import { PropTypes } from "prop-types";
const MyComponent = ({ name }) => {
return <div>{name}</div>;
};
MyComponent.defaultProps = {
name: "김다은",
};
MyComponent.propTypes = {
name: PropTypes.string,
};
export default MyComponent;
이외에도 propTypes는 다양하게 설정할 수 있습니다.
● 클래스형 컴포넌트, props, propTypes
** 클래스형 컴포넌트를 사용할 때는 { Component } 를 import 해옵니다.
import { Component } from "react";
class App extends Component{
render(){
return(<div>안녕하세요? 클래스형 컴포넌트입니다.</div>)
}
}
App.js
import "./App.css";
import MyComponent from "./MyComponent";
function App() {
return (
<div>
안녕하세요? 함수형 컴포넌트 입니다.
<MyComponent name={"다은"} />
</div>
);
}
export default App;
MyComponent.js
import { Component } from "react";
class MyComponent extends Component {
render() {
const { name } = this.props;
return <div>안녕하세요? {name}입니다.</div>;
}
}
export default MyComponent;
클래스에서 defaultProps, propTypes는 함수형과 똑같이 정의할 수 있으며,
import { Component } from "react";
import { PropTypes } from "prop-types";
class MyComponent extends Component {
render() {
const { name } = this.props;
return <div>안녕하세요? {name}입니다.</div>;
}
}
MyComponent.defaultProps = {
name: "기본이름",
};
MyComponent.propTypes = {
name: PropTypes.string,
};
export default MyComponent;
아래와 같이 class 내부 안에서 정의 내릴 수도 있습니다.
import { Component } from "react";
import { PropTypes } from "prop-types";
class MyComponent extends Component {
static defaultProps = {
name: "기본이름",
};
static propTypes = {
name: PropTypes.string,
};
render() {
const { name } = this.props;
return <div>안녕하세요? {name}입니다.</div>;
}
}
export default MyComponent;
● state
⚬ 클래스형 컴포넌트
import { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
// state의 초깃값 설정하기
this.state = {
number: 0,
};
}
render() {
const { number } = this.state; // state를 조회할 때에는 this.state로 조회합니다.
return (
<div>
<h1>{number}</h1>
<button
onClick={() => {
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
클래스형 컴포넌트에서는 constructor를 작성할 때에는 꼭 super(props)를 작성해 주어야합니다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Componenet 클래스가 지닌 생성자 함수를 호출해줍니다.
즉, Counter라는 클래스가 컴포넌트로 쓰일 수 있게 리액트의 Component 클래스의 프로퍼티들을 상속받는다는 것 입니다. 그래서 super을 써서 Counter 클래스 내부의 컴포넌트와 연결시켜주는 것임
그다음 this.state 값에 초기값을 설정해주었습니다. 컴포넌트의 state는 객체 형식이어야합니다.
render 함수에서 state를 확인하기 위해서는 this.state를 사용해주면 됩니다. button 안에는 onClick 라는 값을 props로 넣어 주었는데, 이는 버튼이 클릭 되었을 때 호출시킬 함수를 설정할 수 있게 해줍니다.
이를 이벤트를 설정한다고 하는 것입니다..!
이벤트로 설정할 함수를 넣어 줄 때에는 화살표 함수 문법을 사용하여 넣어주어야합니다.
함수 내부에서는 this.setState 함수를 사용했는데, 이는 함수가 state의 값을 변경할 수 있게 합니다.
또한, constructor를 선언하지 않고도 state 초기값을 설정할 수 있습니다.
import { Component } from "react";
class Counter extends Component {
// state의 초깃값 설정하기
state = {
number: 0,
fixedNumber: 0,
};
render() {
const { number, fixedNumber } = this.state; // state를 조회할 때에는 this.state로 조회합니다.
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값 : {fixedNumber} </h2>
<button
onClick={() => {
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
만약 버튼을 눌렀을 때 2씩 증가하게 만들고 싶다면, 아래와 같이 적어선 안됩ㄴ디ㅏ..
<button
onClick={() => {
this.setState({ number: number + 1 });
this.setState({ number: this.state.number + 1 });
}}
>
+1
</button>;
this.setState 함수 안에, 콜백함수를 넣어서 수정해주면 해결이 됩니다!
<button
onClick={() => {
this.setState((prevState) => {
return {
number: prevState.number + 1,
};
});
this.setState((prevState) => ({ number: prevState.number + 1 }));
}}
>
+1
</button>;
위의 setState 함수와, 아래의 함수식은 똑같은 것입니다.
⚬ this.setState가 끝난 후 특정 작업 실행하기
setState를 사용하여 값을 업데이트하고 난 다음 특정 작업을 하고 싶을 때는 두 번째 setState의 두번 째 파라미터에 콜백함수를 등록하여 작업을 처리할 수 있습니다.
<button
onClick={() => {
this.setState({ number: number + 1 }, () => {
console.log("방금 setState가 호출되었습니다.");
console.log(this.state);
});
}}
>
+1
</button>;
⚬ 함수형 컴포넌트에서 useState 사용하기
원래 함수형 컴포넌트에서는 state를 사용할 수 없었지만, 16.8 이후 useState라는 함수를 사용하여 사용할 수 있게 되었습니다.
useState는 Hooks입니다.
import { useState } from "react";
const Say = () => {
const [message, setMessage] = useState("");
const onClickEnter = () => setMessage("안녕하세요!");
const onClickLeave = () => setMessage("안녕히가세요!");
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1>{message}</h1>
</div>
);
};
export default Say;
함수형 컴포넌트는 useState 함수를 활용해 state를 선언합니다. 초기값은 클래스 컴포넌트와 다르게 객체일 필요가 없습니다. 아무 값이나 상관이 없으며, 함수를 호출하면 배열이 반환됩니다. 배열의 첫번째 원소는 현재 상태이고, 두번째는 상태를 변경시킬 수 있는 함수입니다. 이를 setter 새터라고 부릅니다.