props컴포넌트에 직접 주입하는 값을 props라고 한다.
children도 props의 일부이다.props로 className이나 여러 handler를 줄 수도 있다.컴포넌트 합성
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
컴포넌트 추출
props 기본 사용법App 컴포넌트에서 Fruit 컴포넌트를 사용할 때, 'name' 값을 전달해주고 싶다면 다음처럼 하면 된다.
const App = () => {
return (
<Fruit name="Apple" />
)
}
그리고 전달한 값을 Fruit 컴포넌트에서 사용하려면 Fruit 컴포넌트 인자로 props를 전달해주고, props.name으로 접근해서 name 값을 사용할 수 있다.
이때, props는 객체 형태로 전달된다!
const Fruit = (props) => {
return (
<>
<div>{props.name}</div>
</>
)
}
👉 실행결과

propsFruit 컴포넌트에 다른 props(color, emoji)도 전달해보았다.
Fruit 컴포넌트에서 이를 받아와서 props.color로 배경색을 지정하고, props.name 아래에 props.emoji도 출력해보았다.
const Fruit = (props) => {
return (
<>
<div style={{backgroundColor: props.color}}>{props.name}</div>
<div>{props.emoji}</div>
</>
)
}
const App = () => {
return (
<>
<Fruit name="Apple" color="Red" emoji="🍎" />
<br/>
<Fruit name="Banana" color="Yellow" emoji="🍌" />
</>
)
}
👉 실행결과

🤔 비구조화 할당
매번 접근할 때마다props.~~~을 입력하는 게 번거롭다면, Fruit의 인자에 비구조화 할당을 사용하여 좀 더 간결하게 작성할 수도 있다.const Fruit = ({name, color, emoji}) => { return ( <> <div style={{backgroundColor: color}}>{name}</div> <div>{emoji}</div> </> ) }
defaultProps컴포넌트에 props 값을 지정하지 않았을 때, 기본값을 설정할 수 있다.
name, color, emoji의 기본값으로 모두 ???을 주었다.
const Fruit = (props) => {
return (
<>
<div style={{backgroundColor: props.color}}>{props.name}</div>
<div>{props.emoji}</div>
</>
)
}
Fruit.defaultProps = {
name: "???",
color: "???",
emoji: "???"
}
const App = () => {
return (
<>
<Fruit name="Apple" color="Red" emoji="🍎" />
<br />
<Fruit name="Banana" color="Yellow" emoji="🍌" />
<br />
<Fruit />
<br />
<Fruit color="Purple" emoji="🍇" />
</>
)
}
👉 실행결과
props를 아무것도 전달하지 않은 <Fruit /> 는 name, emoji 부분에 모두 '???'이 출력되고 배경색이 바뀌지 않은 것을 알 수 있다. 또한, name을 전달하지 않은 <Fruit color="Purple" emoji="🍇" />는 name 부분에 '???'이 출력된 것을 알 수 있다.

props.childrenFruit 컴포넌트를 감싸는 Wrapper 컴포넌트를 새로 만들었다.
const Wrapper = () => {
return (
<div style={{border: "3px solid black", width: 400, height: 300}}></div>
)
}
const App = () => {
return (
<>
<Wrapper>
<Fruit name="Apple" color="Red" emoji="🍎" />
<br />
<Fruit name="Banana" color="Yellow" emoji="🍌" />
<br />
<Fruit />
<br />
<Fruit color="Purple" emoji="🍇" />
</Wrapper>
</>
)
}
👉 실행결과
실행해보면 Fruit 컴포넌트들이 화면에 출력되지 않았다.

❗ 이때, Wrapper 컴포넌트에 props를 전달하여 props.children을 렌더링 해주어야 한다.
const Wrapper = (props) => {
return (
<div style={{border: "3px solid black", width: 400, height: 300}}>
{props.children}
</div>
)
}
👉 실행결과
Wrapper 태그 내부에 있던 Fruit가 모두 잘 출력되었다.

State공식 문서에 나와있는 클래스 컴포넌트로 구현된 시계 예제를 함수형 컴포넌트로 똑같이 구현할 수 있다.
| 클래스 컴포넌트 | 함수형 컴포넌트 |
|---|---|
DidMount() | useEffect(...,[]) |
WillUnmount() | useEffect에서 return으로 cleanup |
this.state로 초기화, tick()에서 업데이트 | usetState에서 set할 때 초기화, tick()에서 업데이트 |
setState() | useState() |
|---|---|
| 클래스형 컴포넌트에서 State 관리 | 함수형 컴포넌트에서 State 관리 |
setState() 사용 시 유의할 점State를 수정 ❌, 직접 수정하면 렌더가 되지 않아서 화면에 출력되지 않는다.// ❌ Wrong
this.state.comment = 'Hello';
// ⭕ Correct
this.setState({comment: 'Hello'});State 업데이트는 비동기적setState() 호출을 한꺼번에 처리할 수 있다. 이때 기대한 값과 다른 값이 나올 수 있는데, 이는 콜백함수를 사용하여 해결할 수 있다.// ❌ Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
// ⭕ Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));setState()를 호출할 때 리액트는 제공한 객체를 현재 State로 병합한다.🤔 함수형 vs 클래스
현재는 함수형 컴포넌트에 Hook이 추가되면서 클래스 컴포넌트보다 함수형 컴포넌트가 주로 사용된다.
공식문서 - React.Component
공식문서 - 생명주기 도표