React 뿌시기 3일차 (3) - Feat. 리액트를 다루는 기술
3장 컴포넌트
컴포넌트의 기능은 단순히 템플릿 이상
1) 데이터가 주어졌을 때 이에 맞추어 UI를 만들어 줌
2) 라이프사이클 API를 이용하여 컴포넌트가 화면에서 나타날 때, 사라질 때, 변화가 일어날 때 주어진 작업들을 처리
3) 임의 메소드를 만들어 특별한 기능을 붙여줄 수 있음
컴포넌트의 기능은 단순히 템플릿 이상
1) 데이터가 주어졌을 때 이에 맞추어 UI를 만들어 줌
2) 라이프사이클 API를 이용하여 컴포넌트가 화면에서 나타날 때, 사라질 때, 변화가 일어날 때 주어진 작업들을 처리
3) 임의 메소드를 만들어 특별한 기능을 붙여줄 수 있음
클래스형 컴포넌트
컴포넌트를 선언하는 방식 (두 가지)
1) 함수형 컴포넌트
2) 클래스형 컴포넌트
1) 함수형 컴포넌트
import React from 'react';
import './App.css';
function App() {
const name = '리액트';
return <div className="react">{name}</div>
}
export default App;
2) 클래스형 컴포넌트 (extends Component)
import React, { Component } from 'react';
class App extends Component {
render() {
const name = '리액트';
return <div className="react">{name}</div>
}
}
export default App;
클래스형 컴포넌트, 함수형 컴포넌트의 차이점
클래스형 컴포넌트의 경우
1) state 기능 및 라이프사이클 기능을 사용할 수 있음
2) 임의 메서드를 정의할 수 있음
클래스형 컴포넌트
- Render 함수가 꼭 있어야 함
- 그 안에서 보여 주어야 할 JSX를 반환해야 함
함수형 컴포넌트의 장점
- 클래스형 컴포넌트보다 선언하기가 훨씬 편함
- 메모리 자원도 클래스형 컴포넌트보다 덜 사용
- 배포 후에도 파일 크기가 더 작음
함수형 컴포넌트의 단점
- state와 라이프사이클 API의 사용이 불가능
=> But. Hooks 기능 도입 후 해결!
※ 리액트 공식 문서에서는 함수형 컴포넌트 + Hooks의 사용을 권장!
컴포넌트 생성
// in MyComponent.js
import React from 'react';
// 함수형 컴포넌트
const MyComponenet = () => {
return <div>나의 새롭고 멋진 컴포넌트 :)</div>;
}
export default MyComponenet;
// * 모듈 내보내기 (export)
// -------------------------------------------------
// in App.js
import React from 'react';
// * 모듈 불러오기 (import)
import MyComponenet from './MyComponent';
const App = () => {
return <MyComponent/>;
};
export default App;
// in MyComponent.js
import React from 'react';
// 함수형 컴포넌트
const MyComponenet = () => {
return <div>나의 새롭고 멋진 컴포넌트 :)</div>;
}
export default MyComponenet;
// * 모듈 내보내기 (export)
// -------------------------------------------------
// in App.js
import React from 'react';
// * 모듈 불러오기 (import)
import MyComponenet from './MyComponent';
const App = () => {
return <MyComponent/>;
};
export default App;
props
- properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소
- props 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정 가능
1) JSX 내부에서 props 렌더링
import React from 'react';
const MyComponenet = (props) => {
return <div>나의 새롭고 멋진 컴포넌트 :) {props.name}</div>;
}
export default MyComponenet;
import React from 'react';
const MyComponenet = (props) => {
return <div>나의 새롭고 멋진 컴포넌트 :) {props.name}</div>;
}
export default MyComponenet;
props 값은 컴포넌트 함수의 파라미터로 받아 와서 사용할 수 있음
2) 컴포넌트를 사용할 때 props 값 지정하기
return (
<MyComponenet name="react" />
);
3) props 기본값 설정: defaultProps
// in MyComponent.js
MyComponent.defaultProps = {
name : '기본 이름'
}
4) 태그 사이의 내용을 보여 주는 children
리액트 컴포넌트를 사용할 때 컴포넌트 태그 사이의 내용을 보여 주는 props
import React from 'react';
const MyComponenet = (props) => {
return <div>나의 새롭고 멋진 컴포넌트 :) {props.children}</div>;
}
// in App.js
export default MyComponenet;
return (
<MyComponenet name="react"> 으아아악 </MyComponenet>
);
5) 비구조화 할당 문법을 통해 props 내부 값 추출
- 비구조화 할당 ( = 구조 분해 문법)
- 함수의 파라미터 부분에서도 사용 가능
=> 만약 함수의 파라미터가 객체라면 그 값을 바로 비구조화해서 사용 가능
const { name, children } = props;
// or
const MyComponent ({name, children}) => {
...
}
6) propTypes를 통한 props 검증
7) isRequired를 사용한 propTypes 설정
컴포넌트의 필수 props를 지정하거나 props 타입을 지정할 때는 propTypes를 사용
컴포넌트의 propTypes를 지정하는 방법
import React from 'react';
import PropTypes from 'prop-types';
const MyComponenet= ({ name, children}) => {
...
}
MyComponenet.defaultProps = {
name: '기본 이름'
}
MyComponenet.propTypes = {
name: PropTypes.string
// name: PropTypes.string.isRequired
}
이렇게 설정해 주면 name 값은 무조건 문자열 형태로 전달해야 된다는 것을 의미!
만약 컴포넌트에 설정한 props가 propTypes에서 지정한 형태와 일치하지 않는다면
오류 메시지 출력!
8) PropTypes 종류
- array
- arrayOf
- bool
- func
- number
- object
- string
- symbol
- node : 렌더링 할 수 있는 모든 것(숫자, 문자열 or JSX코드)
- instanceOf(클래스)
- oneOf(['dog', 'cat']) : 주어진 배열 요소 중 값 하나
- oneOfType([React.PropTypes.string, PropTypes.number]) : 주어진 배열 안의 종류 중 하나
- objectOf() : 객체의 모든 키 ㄱ밧이 인자로 주어진 PropType인 객체
- shape()
- any : 아무 종류
9) 클래스형 컴포넌트에서 props 사용하기
- render 함수에서 this.props를 조회!
- defaultProps와 propTypes는 똑같은 방식으로 설정
- defaultProps와 propTypes를 class 내부에서 지정할 수도 있음
class MyComponent extends Component {
static defaultProps = {
name : '기본 이름'
};
static propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
};
render() {
const {name, favoriteNumber, children} = this.props; // 비구조화 할당
return (...);
}
}
state
- props : 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값
- 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용 (read only), 부모 컴포넌트에서만 props를 바꿀 수 있음!
- state : 컴포넌트 내부에서 바뀔 수 있는 값
1) 클래스형 컴포넌트가 지니는 state
2) 함수형 컴포넌트에서 useState라는 함수를 통해 사용하는 state
1) 클래스형 컴포넌트의 state
import React, {Component} from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { // 컴포넌트 내부에서 가질 수 있는 값
number : 0
};
}
render() {
const {number} = this.state;
// state를 조회할 때는 this.state로 조회
return (
<div>
<h1>{number}</h1>
<button
onClick={() => {
this.setState({number : number + 1});
}}
></button>
</div>
);
}
}
export default Counter;
컴포넌트에 state를 설정 = constructor 메소드 작성
constructor(props) {
super(props)
// state의 초깃값 설정하기 (컴포넌트의 state는 객체 형식이어야 함)
this.state = {
number : 0
};
}
- 컴포넌트의 생성자 메소드
- 클래스형에서 constructor를 작성할 때는 반드시 super(props)를 호출해주어야 함
- 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해줌
render 함수
render() {
const {number} = this.state; // state를 조회할 때는 this.state로 조회
return (
<div>
<h1>{number}</h1>
<button
onClick={() => {
this.setState({number : number + 1});
}}
></button>
</div>
);
}
- 현재 state를 조회할 때는 this.state를 조회하면 O
- 이벤트 설정 = button 안에 onClick이라는 값을 props로 넣어 주었는데, 버튼이 클릭될 때 호출시킬 함수를 설정할 수 있게 해줌
- 이벤트로 설정할 함수를 넣어 줄 때는 화살표 함수 문법을 사용해 넣어 주어야 함
- 함수 내부에서는 this.setState라는 함수를 사용
=> 이 함수가 state 값을 바꿀 수 있게 해줌
state 객체 안에 여러 값이 있을 때
import React, {Component} from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { // 컴포넌트 내부에서 가질 수 있는 값
number : 0,
fixedNumber : 0
};
}
render() {
const {number, fixedNumber} = this.state; // state를 조회할 때는 this.state로 조회
return (
<div>
<h1>{number}</h1>
<h1>{`바뀌지 않는 값 ${fixedNumber}`}</h1>
<button
onClick={() => {
this.setState({number : number + 1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
state를 constructor에서 꺼내기
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 0,
fixedNumber: 0
};
render() {
const { number, fixedNumber } = this.state
}
}
1) 클래스형 컴포넌트가 지니는 state
2) 함수형 컴포넌트에서 useState라는 함수를 통해 사용하는 state
import React, {Component} from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { // 컴포넌트 내부에서 가질 수 있는 값
number : 0
};
}
render() {
const {number} = this.state;
// state를 조회할 때는 this.state로 조회
return (
<div>
<h1>{number}</h1>
<button
onClick={() => {
this.setState({number : number + 1});
}}
></button>
</div>
);
}
}
export default Counter;
constructor(props) {
super(props)
// state의 초깃값 설정하기 (컴포넌트의 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});
}}
></button>
</div>
);
}
=> 이 함수가 state 값을 바꿀 수 있게 해줌
import React, {Component} from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { // 컴포넌트 내부에서 가질 수 있는 값
number : 0,
fixedNumber : 0
};
}
render() {
const {number, fixedNumber} = this.state; // state를 조회할 때는 this.state로 조회
return (
<div>
<h1>{number}</h1>
<h1>{`바뀌지 않는 값 ${fixedNumber}`}</h1>
<button
onClick={() => {
this.setState({number : number + 1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 0,
fixedNumber: 0
};
render() {
const { number, fixedNumber } = this.state
}
}
이렇게 하면 constructor 메소드를 선언하지 않고도 state 초깃값을 설정할 수 있음!
this.setState에 객체 대신 함수 인자 전달하기
<Button
onClick={() => {
this.setState(prevState => {
return {
number : prevState.number + 1;
};
});
this.setState(prevState => ({
number : prevState.number + 1;
}));
}}
/>
화살표 함수에서 값을 바로 반환하고 싶다면 코드 블록 { } 를 생략하면 됨!
예를 들어, a,b를 받아서 합을 구한다면 다음과 같이 작성할 수 있음
const sum = (a,b) => a+b;
onClick에서 두 번째로 this.setState 함수를 사용할 때는 화살표 함수에서 바로 객체를 반환하도록 했기 때문에 prevState => ({})와 같은 형태로 코드가 이루어짐
this.setState가 끝난 후 특정 작업 실행하기
<button
onClick={() => {
this.setState({
number : number + 1
},
() => {
console.log(number);
})
}
}
>
this.setState(변경할 state 정보, 콜백 함수)
2) 함수형 컴포넌트에서 useState 사용하기
- 리액트 버전 16.8 이후부터 useState 함수를 사용하여 함수형 컴포넌트에서도 state를 사용할 수 있게 됨
- 이 과정에서 Hooks라는 것을 사용하게 됨
배열 비구조화 할당
배열 안에 들어 있는 값을 쉽게 추출할 수 있도록 해 주는 문법
const array = [1,2];
const [ one, two ] = array;
useState 사용하기
import React, { useState } from 'react';
const Say = () => {
const [ message, setMessage ] = useState('');
// useState 함수 = 인자에 상태의 초깃값을 넣어줌
/**
* 클래스형 컴포넌트에서의 state 초깃값은 객체 형태로 넣어 주어야 함
* useState에서는 반드시 객체가 아니어도 상관없음 (값의 형태는 자유!)
* ex) 숫자, 문자열, 객체, 배열
*
* useState 함수의 return 값 = 함수
* [ 현재 상태, 상태를 바꾸어 주는 함수 (Setter 함수) ]
* => 배열 비구조화 할당을 통해 이름을 자유롭게 정할 수 ㅇ
*/
const onClickEnter = () => setMessage('안녕하세요!');
const onClickLeave = () => setMessage('안녕가세요!');
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1>{message}</h1>
</div>
);
};
export default Say;
한 컴포넌트에서 useState 여러 번 사용하기
- useState는 한 컴포넌트에서 여러 번 사용해도 상관 없음! (각기 다른 state 객체를 만들어줄 때 마다~)
ex)
const [message, setMessage] = useState('')
const [color, setColor] = useState('black')
state를 사용할 때 주의사항
state 값을 바꾸어야 할 때는 setState 혹은 useState를 통해 전달받은 세터 함수를 사용해야 함
// 잘못된 예시! ❌ (in 클래스 컴포넌트)
this.state.number = this.state.number + 1;
// 잘못된 예시! ❌ (in 함수형 컴포넌트)
const [object, setObject] = useState({a:1, b:1});
object.b = 2;
그렇다면 배열이나 객체를 업데이트해야 할 때는 어떻게 해야 할까?
이런 상황에서는 배열, 객체 사본을 만들고 그 사본에 값을 업데이트한 후,
그 사본의 상태를 setState 혹은 세터 함수를 통해 업데이트한다.
사본을 만들어서 업데이트하는 예시
// 객체 다루기
const object = {a:1, b:2, c:3};
const nextObject = { ...object, b:2 };
// 사본을 만들어서 b값만 덮어 쓰기
// 배열 다루기
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);
nextArray.map((item) => (item.id === 1 ? {...item, value: false} : item));
- 객채에 대한 사본을 만들 때
- spread 연산자라 불리는 ...을 사용하여 처리
- 배열에 대한 사본을 만들 때
- 배열의 내장 함수들을 활용
정리
- props는 부모 컴포넌트가 설정하고, state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트!
- props를 사용한다고 해서 값이 무조건 고정적이지 않음
- 부모 컴포넌트의 state를 자식 컴포넌트의 props로 전달하고, 자식 컴포넌트에서 특정 이벤트가 발생할 때 부모 컴포넌트의 메소드를 호출하면 props도 유동적으로 사용 가능
- state를 다루기 위한 방법
1) 클래스형 컴포넌트의 state
2) 함수형 컴포넌트의 useState (앞으로 함수형 컴포넌트, Hooks를 사용하는 것이 주요 컴포넌트 개발 방식이 될 것)
Author And Source
이 문제에 관하여(React 뿌시기 3일차 (3) - Feat. 리액트를 다루는 기술), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@soulee__/React-뿌시기-3일차-3-Feat.-리액트를-다루는-기술
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
- props는 부모 컴포넌트가 설정하고, state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트!
- props를 사용한다고 해서 값이 무조건 고정적이지 않음
- 부모 컴포넌트의 state를 자식 컴포넌트의 props로 전달하고, 자식 컴포넌트에서 특정 이벤트가 발생할 때 부모 컴포넌트의 메소드를 호출하면 props도 유동적으로 사용 가능
- state를 다루기 위한 방법
1) 클래스형 컴포넌트의 state
2) 함수형 컴포넌트의 useState (앞으로 함수형 컴포넌트, Hooks를 사용하는 것이 주요 컴포넌트 개발 방식이 될 것)
Author And Source
이 문제에 관하여(React 뿌시기 3일차 (3) - Feat. 리액트를 다루는 기술), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@soulee__/React-뿌시기-3일차-3-Feat.-리액트를-다루는-기술저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)