컴포넌트에 직접 주입하는 값을 props
라고 한다.
children
도 props
의 일부이다.props
로 className
이나 여러 handler
를 줄 수도 있다.컴포넌트 합성
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
컴포넌트 추출
공식 문서에 나와있는 클래스 컴포넌트로 구현된 시계 예제를 함수형 컴포넌트로 똑같이 구현할 수 있다.
클래스 컴포넌트 | 함수형 컴포넌트 |
---|---|
DidMount() | useEffect(...,[]) |
WillUnmount() | useEffect 에서 return 으로 cleanup |
this.state 로 초기화, tick() 에서 업데이트 | usetState 에서 set할 때 초기화, tick() 에서 업데이트 |
🤔 함수형 vs 클래스
현재는 함수형 컴포넌트에 훅이 추가되면서 클래스 컴포넌트보다 함수형 컴포넌트가 주로 사용된다.
this.setState~
, ❌: this.state~
import React, { Component } from 'react'
export default class ClassComponent extends Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world! It's Class</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
import React, { useState, useEffect } from 'react'
export default function FunctionalComponent() {
const [date, setDate] = useState(new Date());
const tick = () => {
setDate(new Date());
}
useEffect(() => {
const interval = setInterval(() => tick(), 1000);
return () => {
clearInterval(interval);
};
}, []);
return (
<div>
<h1>Hello, world! It's Functional</h1>
<h2>It is {date.toLocaleTimeString()}.</h2>
</div>
)
}
this
로 관리, 함수형 컴포넌트에서는 useState
라는 Hook으로 관리한다.공식문서 - React.Component
공식문서 - 생명주기 도표
공식문서 - 합성 이벤트(SynthenticEvent)
공식문서 - 이벤트 처리하기
SynthenticEvent
객체를 전달받는다.false
를 반환해도 기본 동작을 방지할 수 없다. 반드시 preventDefault
를 명시적으로 호출해야 한다.🤔 Bubbling? Capturing?
- Bubbling: 자식으로부터 부모로 올라가는 것.
- Capturing: 부모로부터 자식이 언제 이벤트가 있는지 체크하는 것.
- Event 순서:
다음과 같은 구조에서 버튼을 클릭했을 때 이벤트 발생 순서는handleClickCapture
→handleClickCapture2
→handleButtonClick
→handleClickBubble
이다.<div onClickCapture={handleClickCapture}> <div onClickCapture={handleClickCapture2} onClick={handleClickBubble}> <button onClick={handleButtonClick}>Button</button> </div> </div>
공식문서 - 조건부 렌더링(Conditional Rendering)
true && A
는 항상 A
로 평가되고 false && A
는 항상 false
로 평가된다. 이때, falsy한 값인 0
(false는 아님! falsy!!)이 들어오면 false
로 평가되는 것이다.🤔 falsy한 값(0) 처리
1.Boolean()
{Boolean(props.count) && `It's ${props.count} times`}
- 삼항연산자
{props.count ? `It's ${props.count} times` : null}
import React from 'react'
function UserGreeting(props) {
return <h1>{props.name && props.name + ',' } Welcome {props.count ? `It's ${props.count} times` : null}</h1>
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>
}
function Greeting(props) {
// if(props.isLoggedIn) {
// return <UserGreeting name="doyoung" count={0} />
// }
// return <GuestGreeting />;
return props.isLoggedIn ? <UserGreeting name="Doyoung" count={1} /> : <GuestGreeting />;
}
export default function Condition() {
const isLoggedIn = true;
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
</div>
)
}
key
는 엘리먼트의 고유성을 부여하기 위해서(식별하기 위해서) 사용되는 것일 뿐, 값을 가져다가 사용할 수는 없다.key
는 props
가 아니다.key
는 컴포넌트 전체에서 고유해야 하는 것이 아니라 map()
으로 묶여있는 list 내부에서만 고유하면 된다.key
값을 index를 넣어줄 수도 있지만, 항상 고유한 값은 아니다.import React, { useState } from 'react'
export default function ControlledComponent() {
const [name, setName] = useState("");
const [essay, setEssay] = useState("Please write an essay about your favorite DOM element.");
function handleChange(event) {
const name = event.target.name;
if (name === 'name') {
setName(event.target.value);
}
if (name === 'essay') {
setEssay(event.target.value);
}
}
// function handleEssayChange(event) {
// setEssay(event.target.value);
// }
function handleSubmit(event) {
alert(`name: ${name}, essay: ${essay}`);
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input name="name" type="text" value={name} onChange={handleChange} />
</label>
<br />
<br />
<label>
Essay:
<textarea name="essay" value={essay} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
)
}
import React, { useRef } from 'react'
export default function UncontrolledComponent() {
const fileInputRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
alert(`Selected file - ${fileInputRef.current.files[0].name}`);
}
return (
<div>
<form onSubmit={handleSubmit}>
<br />
<label>
Upload file:
<input type="file" ref={fileInputRef} />
</label>
<br />
<button type="submit">Submit</button>
</form>
</div>
)
}
useState
를 통해 관리하며, 하나의 핸들러만을 가지고 다중 입력을 제어할 수 있다.useRef
를 사용한다. (~.current.value
, ~.files[n].name
)🤔 VSCode 추천 확장 프로그램
- Rainbow Brackets
- indent-rainbow
- ESLint
- npm
🤔 VSCode 단축어
rfc: reactFunctionalComponent
rcc: reactClassComponent