컴포넌트의 기능은 단순한 템플릿 이상이다
- 데이터가 주어졌을 때 UI 생성
- 라이프사이클 API를 이용하여 컴포넌트가 화면에서 나타나거나 사라지는 등 변화가 나타날 때 주어진 작업을 처리
- 임의 메서드를 만들어 특별한 기능을 추가
클래스형 컴포넌트
import { Component } from 'react';
class App extends Component {
// render 함수가 꼭 필요하다.
render() {
const name = 'react';
return <div>{name}</div>
}
}
export default App;
클래스형 컴포넌트와 함수 컴포넌트 차이
클래스형 컴포넌트
- 객체지향 프로그래밍 구조를 가지며, state를 초기화 하기 위해 constructor을 가진다.
- 코드가 길고 사이즈가 크다. (함수 컴포넌트에 비해)
- state 기능 및 라이프 사이클 기능을 사용할 수 있다.
- render 함수가 꼭 있어야 한다.
함수 컴포넌트
- Hooks를 사용하여 생성자 함수를 통해 state를 초기화 하지 않더라도 사용이 가능하다. (useState())
- 선언하기가 좀 더 편하고, 메모리 자원을 덜 사용한다.
- 제공되는 Hooks 함수뿐만 아니라 커스텀 훅을 만들 수 있다.
- state와 라이프사이클 API가 사용이 불가능하다. (⇒ v16.8 이후 Hooks로 해결)
* 리액트 공식 메뉴얼에서는 컴포넌트를 새로 작성할 때 함수 컴포넌트와 Hooks를 사용하도록 권장한다.
* 클래스 컴포넌트가 사라지는 것은 아니니, 클래스 컴포넌트의 기능은 꼭 알아두어야 한다.
props
정의
컴포넌트 속성을 설정할 때 사용하는 요소
props 값은 해당 컴포넌트를 호출하는 부모 컴포넌트에서 설정할 수 있다.
1. JSX 내부에서 props 렌더링
MyComponents 컴포넌트에서 props를 렌더링 하도록 수정하면 다음과 같다.
const MyComponent = (props) => { // 이때 props는 {'name': 넘겨준 값} 형태로 받아진다.
return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>
}
export default MyComponent;
2. 컴포넌트를 사용할 때 props 값 지정하기
MyComponents를 호출하는 App.js에서 props를 지정할 수 있다.
import MyComponent from './MyComponent';
const App = () => {
return <MyComponent name='이수화'/>;
};
export default App;
3. props 기본값 설정: defaultProps
이렇게 props를 직접 넘겨주지 않고, 컴포넌트 내에서 기본값을 설정하고 싶다.
⇒ defaultProps를 사용
import MyComponent from './MyComponent';
const App = () => {
return <MyComponent/>; // name의 값을 지정 x
};
export default App;
const MyComponent = (props) => {
return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>
}
MyComponent.defaultProps = {
name: '기본값'
}
export default MyComponent;
4. 태그 사이의 내용을 보여주는 children
컴포넌트 태그 사이의 내용을 보여주고 싶다.
⇒ children을 사용
- 상위 컴포넌트 : App.js
import MyComponent from './MyComponent';
const App = () => {
return <MyComponent>이수화</MyComponent>;
};
export default App;
- 하위 컴포넌트 : MyComponent.js
const MyComponent = (props) => {
return <div>
안녕하세요, 제 이름은 {props.name}입니다.
children 값은 {props.chilren}입니다.
</div>
}
MyComponent.**defaultProps** = {
name: '기본값'
}
export default MyComponent;
5. 비구조화 할당 문법을 통해 props 내부 값 추출하기
props 내부의 프로퍼티를 접근할 때 **props.**이 붙는게 불편하다.
⇒ 비구조화 할당으로 내부값을 바로 추출
const MyComponent = (props) => {
const {name, children} = props;
return <div>
안녕하세요, 제 이름은 {name}입니다.
children 값은 {chilren}입니다.
</div>
}
MyComponent.**defaultProps** = {
name: '기본값'
}
export default MyComponent;
- 이렇게도 쓸 수 있다.
const MyComponent = ({name, children}) => {
...
6. propTypes를 통한 props 검증
컴포넌트의 필수 props를 지정하거나 props의 타입을 지정하고 싶다.
⇒ propTypes 사용
import PropTypes from 'prop-types';
const MyComponent = (props) => {
const {name, children} = props;
return <div>
안녕하세요, 제 이름은 {name}입니다.
children 값은 {chilren}입니다.
</div>
}
MyComponent.defaultProps = {
name: '기본값'
}
MyComponent.**propTypes** = {
name: PropTypes.string
};
export default MyComponent;
propTypes란
앱이 커짐에 따라 타입 검사를 활용하면 많은 버그를(bug) 잡을 수 있습니다. 특정 애플리케이션에서는 전체 애플리케이션의 타입 검사를 위해 Flow 또는 TypeScript와 같은 JavaScript 도구(Extensions)를 사용할 수 있습니다. 이러한 것들을 사용하지 않더라도 React는 내장된 타입 검사 기능들을 가지고 있습니다. 컴포넌트의 props에 타입 검사를 하려면 다음과 같이 특별한 프로퍼티인 propTypes를 선언할 수 있습니다.
isRequired 속성으로 type을 필수로 지정하도록 할 수 있다.
MyComponent.propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired,
};
7. 클래스형 컴포넌트에서 props 사용하기
클래스형 컴포넌트에서 props를 사용할 때는 render 함수에서 this.props를 조회하면 된다.
그 외는 함수 컴포넌트와 유사하다.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component {
static defaultProps = {
name: '기본 이름',
};
static propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired,
};
render() {
const { name, favoriteNumber, children } = this.props; // 비구조화 할당
return (
<div>
안녕하세요, 제 이름은 {name} 입니다. <br />
children 값은 {children}
입니다.
<br />
제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
}
}
MyComponent.defaultProps = {
name: '기본 이름'
};
MyComponent.propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
};
export default MyComponent;
state
정의
- 컴포넌트 내부에서 쉽게 바뀔 수 있는 값
react는 총 2개의 state가 있다.
- 클래스형 컴포넌트가 지니고 있는 state
- 함수 컴포넌트에서 useState라는 함수를 통해 사용하는 state
클래스형 컴포넌트의 state
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 0,
fixedNumber: 0
};
render() {
const { number, fixedNumber } = this.state; // state 를 조회 할 때에는 this.state 로 조회합니다.
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값: {fixedNumber}</h2>
<button
// onClick 을 통하여 버튼이 클릭됐을 때 호출 할 함수를 지정합니다.
onClick={() => {
// this.setState(prevState => {
// return {
// number: prevState.number + 1
// };
// });
// // 위 코드와 아래 코드는 완전히 똑같은 기능을 하는 코드입니다.
// // 아래 코드는 함수에서 바로 객체를 반환한다는 의미입니다.
// this.setState(prevState => ({
// number: prevState.number + 1
// }));
this.setState(
{
number: number + 1
},
() => {
console.log('방금 setState 가 호출되었습니다.');
console.log(this.state);
}
);
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
함수 컴포넌트에서 useState 사용하기
react 16.8 이전 버전에서는 함수 컴포넌트에서 state를 사용할 수 없었지만, 16.8 이후 useState 함수를 사용하여 함수 컴포넌트에서도 state를 사용할 수 있게 되었다.
배열 비구조화 할당
const array = [1, 2];
const one = array[0];
const two = array[1];
// 비구조화 할당
const [one, two] = array;
useState 사용하기
- 사용
const [message, setMessage] = useState(''); // 인자 : 상태의 초깃값
// 반환 받는 값 : 현재 상태, 상태를 바꾸어주는 함수(세터 함수)
- 예제
import React, { useState } from 'react';
const Say = () => {
const [message, setMessage] = useState('');
const onClickEnter = () => setMessage('안녕하세요!');
const onClickLeave = () => setMessage('안녕히 가세요!');
const [color, setColor] = useState('black'); // useState는 여러개 사용할 수 있다.
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1 style={{ color }}>{message}</h1>
<button style={{ color: 'red' }} onClick={() => setColor('red')}>
빨간색
</button>
<button style={{ color: 'green' }} onClick={() => setColor('green')}>
초록색
</button>
<button style={{ color: 'blue' }} onClick={() => setColor('blue')}>
파란색
</button>
</div>
);
};
export default Say;
state의 불변성
불변성 : 메모리 영역에서의 직접적인 변경을 하지 않고, 기존의 값을 수정하지 않으면서 새로운 값을 만들어내는 것
state가 불변성을 지켜야 하는 이유
기존의 state가 불변성을 지켜주어야 리액트 컴포넌트에서 상태가 업데이트 됐음을 감지할 수 있고, 이에 따라 필요한 리렌더링이 진행되기 때문
state를 사용할 때 주의 사항
state의 값을 바꿀때는 반드시 setState 혹은 useState를 통해 전달받은 세터함수를 사용해야 한다 !
배열이나 객체를 업데이트 해야할 때
- 배열이나 객체의 사본을 만들고, 그 사본에 값을 업데이트 한 후 setState 혹은 세터 함수를 통해 업데이트한다.
- 사본에 값을 업데이트 하는 예시
const object = {a: 1, b: 2, c: 3};
const nextObject = { ...object, b: 2 }; // 사본을 만들어서 b값만 덮어씀 (스프레드 연산자(js문법))
const array = [
{ id: 1, value: true },
{ id: 2, value: true },
{ id: 3, value: false }
]
let nextArray = array.concat({ id: 4 }); // 배열에 새 항목 추가
nextArray.filter(item => item.id !== 2); // id가 2인 항목 제거
nextArray.map(item => item.id === 1 ? {...item, value: false} : item); // id가 1인 항목의 value를 false로 변경
'React' 카테고리의 다른 글
[React] ref란 (0) | 2023.06.20 |
---|---|
[React] 이벤트 핸들링 (0) | 2023.06.20 |
[React] 리액트란 (0) | 2023.06.20 |
[React] 리덕스 미들웨어 (0) | 2023.05.30 |
[React] 리액트 라우터 (1) | 2023.05.02 |