컴포넌트의 기능은 단순 템플렛 이상
props
/ 상태값 state
계속 봐왔던 App 컴포넌트는 함수 컴포넌트
function App() {
const name = "react";
return <div className="react">{name}</div>;
}
export default App;
컴포넌트를 선언하는 방식은 두가지다.
클래스형 컴포넌트는 다음과 같이 생겼다.
class App extends Component {
render() {
const name = "react";
return <div className="react">{name}</div>;
}
}
클래스형 컴포넌트와 함수형 컴포넌트 차이
state
기능클래스형 컴포넌트는
그럼 언제 어떤걸 사용하나?
state
사용 안됨Hooks
기능 도입후 극복리액트 공식문서도 함수 컴포넌트 + hooks 사용을 권장한다
그러나 클래스형 컴포넌트가 사라지는건 아님
const MyComponent = () => {
return <div> 나의 멋진 컴포넌트</div>;
};
export default MyComponent;
function
키워드 대신에 () => {}
를 사용했다. 이는 ES6의 화살표 함수 문법
화살표 함수는 사용용도가 다르다. 주로 함수를 파라미터로 전달할 때 유용하다
기존 function을 대체할 수 없다. 왜냐하면 용도가 다르기 때문
무엇보다 가르키는 this값이 다르다
function BlackDog() {
this.name = '흰둥이';
return {
name: '검둥이',
bark: function(){
console.log( this.name + ': 멍멍!');
}
}
}
const blackDog = new BlackDog();
blackDog.bark(); // 검둥이: 멍멍
function WhiteDog() {
this.name = '흰둥이';
return {
name: '검둥이',
bark: function(){
console.log( this.name + ': 멍멍!');
}
}
}
const whiteDog = new WhiteDog();
whiteDog.bark(); // 흰둥이: 멍멍
function()
사용시는 검둥이가,() =>
는 흰둥이가 나타난다.
일반 함수는 자신이 종속된 객체를 this로 가르키며, 화살표 함수는 자신이 종속된 인스턴스를 가르킨다.
또한 값을 연산하여 바로 반환 할 때 사용해도 가독성을 높인다
function twice(value){
return value*2;
}
const triple = (value) => value*3;
따로 {}
를 열어주지 않으면 값을 그대로 반환한다는 의미이다.
다음 코드는 뭘까?
export default MyComponent;
이 코드는 다른 파일에서 이 파일을 import 할 때, 위에서 선언한 MyComponent 클래스를 불러오도록 설정한다.
그럼 App 컴포넌트에서 MyComponent를 사용하려면 다음과 같이 사용한다.
import MyComponent from "./MyComponent";
const App = () => {
return <MyComponent />;
};
MyComponent가 name
이라는 props
를 렌더링 해보자.
// App.js
const App = () => {
return <MyComponent name="React" />;
};
// MyComponent.js
const MyComponent = (props) => {
return <div> 내 이름은 {props.name} 입니다.</div>;
};
만약 App.js
의 ;에서 name 프로퍼티를 지우면 어떻게 될까?
name값을 지정하지 않았기에 내 이름은 입니다.
가 출력된다.
property값을 지정하지 않았을 때 보여줄 기본 값을 defaultProps로 설정할 수 있다.
const MyComponent = (props) => {
return <div> 내 이름은 {props.name} 입니다.</div>;
};
MyComponent.defaultProps = {
name: "기본 이름",
};
export default MyComponent;
리액트 컴포넌트 사용할 때 컴포넌트 태그 사이의 내용을 보여주는 props를 children이다
//App.js
const App = () => {
return <MyComponent>태그 안 내용</MyComponent>;
};
//MyComponent.js
const MyComponent = (props) => {
return (
<div>
내 이름은 {props.name} 입니다.
<br /> children 값은{props.children} 입니다.
</div>
);
};
비구조화 할당/구조 분해 문법이라고 부른다.
const MyComponent = props => {
const { name, children } = props;
return (
<div>
내 이름은 {name} 입니다.
<br /> children 값은{children} 입니다.
</div>
);
};
함수의 파라미터 부분에서도 사용할 수 있다.
props
를 사용한다면, 바로 비구조화 할당 문법을 사용하자.
//개선된 버전
const MyComponent = ({ name, children }) => {
return (
<div>
내 이름은 {name} 입니다.
<br /> children 값은{children} 입니다.
</div>
);
};
컴포넌트의 필수 props를 지정하거나, props의 타입을 지정할 때는 propTypes
를 사용한다. defaultProps와 비슷하다.
MyComponent.propTypes = {
name: PropTypes.string,
};
만약 name prop에 숫자를 넣는다면
const App = () => {
return <MyComponent name={3}>태그 안 내용</MyComponent>;
};
다음과 같은 오류가 발생한다
failed prop type: Invalid prop
name
of typenumber
supplied toMyComponent
, expectedstring
.
propTypes를 지정하지 않았을 때 경고 메시지를 띄울 수 있다.
propTypes를 지정할 때 뒤에 isRequired를 붙여주면 된다.
const MyComponent = ({ name, favoriteNumber, children }) => {
return (
<div>
내 이름은 {name} 입니다.
<br /> children 값은{children} 입니다.
<br /> 제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
};
...
MyComponent.propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired,
};
마찬가지로 다음 오류가 발생한다
Failed prop type: The prop
favoriteNumber
is marked as required inMyComponent
, but its value isundefined
.
클래스형 컴포넌트에서 props를 사용할 때는 render 함수에서 this.props를 조회하면 된다. defaultProps
, propTypes
는 똑같이 설정한다.
다음과 같이 바꿀 수 있다.
class MyComponent extends Component {
render() {
const { name, favoriteNumber, children } = this.props;
return (
<div>
내 이름은 {name} 입니다.
<br /> children 값은{children} 입니다.
<br /> 제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
}
}
defaultProps와 propTypes를 꼭 사용해야 하나요?
필수 사항은 아니지만, 큰 프로젝트에 협업을 해야한다면 쓰자
리액트에서 state
는 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.
MyComponent
에서는 전달받은 name값을 직접 바꿀 수 없음리액트는 두가지 state
가 있다.
state
state
//Counter.js
import { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
number: 0,
};
}
render() {
const { number } = this.state;
return (
<div>
<h1>{number}</h1>
<button
onClick={() => {
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
클래스형 컴포넌트에 state를 설정할 때는 constructor
메서드를 작성하여 설정한다.
컴포넌트 생성자 메서드에서 반드시 super(props)
를 호출해 주어야 한다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속하고 있는 Component 클래스가 지닌 생성자 함수를 호출해 준다.