김민태의 데브캠프 2기 - React 배경지식 + 2하기
React의 기본 규칙
1. 하나의 파일에는 하나의 컴포넌트
2, 실제 파일명과 컴포넌트 명을 동일하게 설정 권고
3. export 키워드를 통해 다른 함수에서 import 가능
클래스
class A extends B
A의 부모가 B
B에서 선언된 메소드를 A에서 사용 가능
class에서의 자식 컴포넌트가 되기 위해서는 다음의 2가지를 만족해야함
1. 생성자(constructor) 선언
생성자 안에서 super(); 호출 필수 -> super란 ? 부모를 호출하는 메소드
super 안에 인자(props)를 담을 시 부모에게도 props의 값이 전달
2. render 메소드 선언
컴포넌트의 UI 반환
React.Fragment(component)
React에서는 html요소들을 한번 감싸야하는데 div로 감싸면 불필요한 div가 생성되므로 React.Fragment를 사용하여 불 필요한 div요소 생성을 막고, 감싸서 오류를 방생시키지 않게 한다.
특징으로는 )
react에서의 최상위 component로 주로 선언
real dom에서는 안 그려짐
축약형으로 <> </>로 사용 가능
클래스 컴포넌트 vs 함수 컴포넌트
- 옛날에는 클래스형 컴포넌트로 많이 썼지만, 요즘에는 함수형 컴포넌트로 많이 돌아가고 있는 추세
- 함수라고 하는 형태 자체로는 상태를 가질 수 없음.
- 앱이 복잡해지면서 lifecycle과 관련된 요구사항이 점점 늘어남
- but. 함수가 상태를 가질 수 없다는 문제를 연구 끝에 hook이라는 개념으로 상쇄시킴
- 상태를 직접 가지지는 않지만, react에서 받아온 데이터를 관리하여 함수에 전달이 가능
클래스형 컴포넌트
다음은 '실시간으로 현재 시간'을 나타내는 ClassClock의 예시이다.
export default class ClassClock extends React.Component {
constructor(props) {
super(props);
}
render() {
const date = new Date();
<div>Class : { date.ToLocaleTimeString() } </div>
}
}
----------------------------------------------------------
//this로 자기 자신을 참조하는 객체를 호출
export default class ClassClock extends React.Component {
constructor(props) {
//props.color = props.color || 'red';
//props.color에 값이 있으면 props.color, 아닐 시 default 값으로 red로 설정
super(props);
this.state = {
date : new Date();
}
setInterval(() => {
this.tick();
}, 1000)
}
tick = () => {
this.setState({
date: new Date();
})
}
render() {
<div>Class : { this.state.date.ToLocaleTimeString() } </div>
}
}
//위 코드에서는 setinterval로 1초마다 호출하는 것인데, 실제 함수 동작하는 시간에 따른
//react dom과 real dom 사이의 time gap이 존재
--------------------------------------------------------------
export default class ClassClock extends React.Component {
constructor(props) {
super(props);
this.state = {
date : new Date();
}
componentDidMount() {
this.timerId = setInterval(() => {
this.tick();
}, 1000)
}
componentWillUnmount() {
clearInterval(this.timerId);
}
//setInterval 함수는 이벤트 시스템에 등록되고, 시스템이 꺼지기 전까지 계속 돌아감 => garbage
//따라서 unmount되면 같이 해제시켜줘야함
}
tick = () => {
this.setState({
date: new Date();
})
}
render() {
const { color } = this.props;
<div style={{ color : color }}>Class : { this.state.date.ToLocaleTimeString() } </div>
}
}
지난 게시글에서 말했듯이, 컴포넌트는 내부에서 자기 자신을 호출할 수 없다(함수, 클래스 동일)
따라서 단순한 함수 호출방법으로는 실시간으로 바뀌어야 하는 시간(상태/데이터)에 대해 UI 실시간으로 반영할 수 없다.
해결 방법은!?
this를 이용한다. this.setState()를 호출
setState는 뭐지!?
React에게 호출해달라는 요청이다.
state는 상태를 의미하며, lifecycle에 따라 메소드를 분리한다.
react dom과 real dom
컴포넌트가 ReactDom에서만 존재하는지, RealDom에 mount 되어 실제 UI로 사용자에게 보여지고 있는지는 React만 알 수 있다.
*mount : 컴포넌트가 RealDom으로 적용되어 보여질 때
*unmount : 아직 보여지지 않을 때
처음으로 RealDom으로 mount되어 unmount 될 때 까지의 시간을 생애주기(life cycle)이라 한다.
mount와 umount 관련 메소드
- componentDidMount()
- component의 상태를 설정하고, 설정된 상태를 기반으로 UI 업데이트
- 화면이 처음 나타난 이후, 특정 DOM 조작이 필요한 경우
- componentWillMount()
- componentDidUpdate()
함수형 컴포넌트
export default function FunctionClock(props) {
const date = new Date();
return(
<div>Function : { date.ToLocaleTimeString() }</div>
)
}
------------------------------------------------
//useState, useEffect를 활용한 상태 변경
export default function FunctionClock(props) {
const [date, setDate] = useState(new Date());
useEffect(() => {
const timerId = setInterval(() => {
setDate(new Date());
}, 1000)
return () => {
clearInterval(timerId);
}
}, [])
return(
<div>Function : { date.ToLocaleTimeString() }</div>
)
}
함수 내에서 state를 가질 수 없다.
따라서 React가 Hook(대신 만들어 놓은 상태를 전달받는 상태)를 통해 해결
보통 커스텀 훅이라 한다.
따로 커스텀하여 사용할 때는 보통 use를 앞에 붙인다. userEffect.. 등
훅의 종류
- useState
- 상태를 만들어주는 hook(바꾸지 x)
- ⇒ 따라서, setState로 상태를 변경
- useState를 할당한 변수 호출 시, 첫 번째는 상태값, 두 번째는 상태 변경 함수를 반환
- 따라서, 구조분해할당을 이용하여 다음과 같이 선언.
- 두번째 값에 상태 변경 함수를 할당하므로, prefix로 변수 이름 앞에 set을 일반적으로 붙임
- ⇒ const [date, setDate] = useState(new Date());
- 따라서, 구조분해할당을 이용하여 다음과 같이 선언.
- useState() 에서 괄호 안의 값은 처음 호출될 때의 초기값.
- 첫 번째 이후로 호출 시에는 기존 값을 무시하고, 이전에 실행한 이후 마지막으로 변경된 값을 반환
- 상태가 바뀐다 -> UI가 바뀐다.
- 보통 암죽적으로 사용됨
- useEffect
- lifecycle과 관련된 훅
- 함수가 real dom에 반영이 되었는지, react dom에서만 돌아가고 있는지 처리하는 훅
- 선언 방식(기본 구조) :return () ⇒ {}, [] )
- 첫 매개변수는 함수, 두번쨰 매개변수는 배열
- 위 구조에서 return과, 마지막 배열 부분은 옵션
- useEffect(() ⇒ {
- useEffect 안의 함수는 real dom에서 사라지기 직전에 호출이 됨(=componentwillunmount)
- []
- 배열 안에 아무것도 없으면, real dom에 붙기 직전에 호출하고, 업데이트 전까지 절대 다시 호출되지 않음.(mount 될 때 최초 한번만 변경) (=componentdidmount)
- 각 상황 이벤트 발생시 매개변수의 함수를 호
lifecycle 관련 메소드 비교
- 클래스는 메소드들의 기능이 매우 명시적(매커니즘을 몰라도 함수명으로 대략적인 추적 가능)
- 함수는 간단명료하지만 암시적(매커니즘을 모르면 추적이 불가능)
react에서 css를 선언 방법
- 태그 내에 inline 방식으로 style 선언
- ex) <div style={{color : red}}>Class : ~~</div>
- style은 값으로 객체를 받음
- 더블 브레이스({})가 아님
- javascript 문법을 jsx에 집어넣을 때 {}
- 객체를 선언할 때 {}
- 객체 내 속성값을 설정할 때, “-”는 허용되지 않음 ⇒ 대문자로 대체
- ex) font-size → fontSize
- 키-벨류 구조에서, 벨류 값은 문자열로 처리해줘야함
- ex) fontSize : '16px'
- component의 파라미터에 바로 객체 할당도 가능(객체 = 값이기 때문에!)
퀴즈 )
위 코드에서 버튼을 클릭해도 ClassClock의 글자색이 변하지 않는 이유는?
실제로 값은 변경되지만 React가 이를 알 수가 없어서 반영을 못한다.
따라서 위에서 설명한 useState와 useEffect를 활용하여 React에게 이벤트 발생을 알려야 한다.
map의 동작 원리
- 값을 map에 넘겨줌
- map이 function에 넘겨줌
- function이 각 결과값마다 배열을 리턴
- 리턴할 때 배열 내의 값은 function을 어떻게 선언했냐(return을 어떻게 설정했냐)에 따라 다를 수 있음.
n개의 배열 원소를 반환하는데, 그 요소 하나하나를 조작 가능하다.