Component
Component๋ ์๋ฐ์คํฌ๋ฆฝํธ class๋ก ์ ์๋ React ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ class์
๋๋ค. React์์ ํด๋์ค ์ปดํฌ๋ํธ๋ฅผ ๊ณ์ ์ง์ํ์ง๋ง, ์ ์ฝ๋์์๋ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ ์ถ์ฒํฉ๋๋ค.
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}- ๋ ํผ๋ฐ์ค
Componentcontextpropsrefsstateconstructor(props)componentDidCatch(error, info)componentDidMount()componentDidUpdate(prevProps, prevState, snapshot?)componentWillMount()componentWillReceiveProps(nextProps)componentWillUpdate(nextProps, nextState)componentWillUnmount()forceUpdate(callback?)getChildContext()getSnapshotBeforeUpdate(prevProps, prevState)render()setState(nextState, callback?)shouldComponentUpdate(nextProps, nextState, nextContext)UNSAFE_componentWillMount()UNSAFE_componentWillReceiveProps(nextProps, nextContext)UNSAFE_componentWillUpdate(nextProps, nextState)static childContextTypesstatic contextTypesstatic contextTypestatic defaultPropsstatic propTypesstatic getDerivedStateFromError(error)static getDerivedStateFromProps(props, state)
- ์ฌ์ฉ๋ฒ
- ๋์
- class์์ ํจ์๋ก ๊ฐ๋จํ ์ปดํฌ๋ํธ ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
- state๊ฐ ์๋ ์ปดํฌ๋ํธ๋ฅผ class์์ ํจ์๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
- ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๊ฐ ์๋ ์ปดํฌ๋ํธ๋ฅผ class์์ ํจ์๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
- context๊ฐ ์๋ ์ปดํฌ๋ํธ๋ฅผ class์์ ํจ์๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
๋ ํผ๋ฐ์ค
Component
React ์ปดํฌ๋ํธ๋ฅผ class๋ก ์ ์ํ๋ ค๋ฉด, ๋ด์ฅ Component class๋ฅผ ํ์ฅํ๊ณ render ๋ฉ์๋๋ฅผ ์ ์ํ์ธ์.
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}render ๋ฉ์๋๋ง ํ์๊ณ ๋ค๋ฅธ ๋ฉ์๋๋ ์ ํ ์ฌํญ์
๋๋ค.
์๋์ ๋ ๋ง์ ์์๋ฅผ ํ์ธํ์ธ์.
context
ํด๋์ค ์ปดํฌ๋ํธ์ context๋ this.context๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. static contextType(modern) ๋๋ static contextTypes(deprecated)๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ค context๋ฅผ ๋ฐ๊ธธ ์ํ๋์ง ์ง์ ํด์ผ๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํด๋์ค ์ปดํฌ๋ํธ๋ ํ ๋ฒ์ ํ๋์ context๋ง ์ฝ์ ์ ์์ต๋๋ค.
class Button extends Component {
static contextType = ThemeContext;
render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}props
ํด๋์ค ์ปดํฌ๋ํธ์ ์ ๋ฌ๋๋ props๋ this.props๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
<Greeting name="Taylor" />refs
์ปดํฌ๋ํธ์ ๋ํ legacy string refs์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
state
ํด๋์ค ์ปดํฌ๋ํธ์ state๋ this.state๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. state ํ๋๋ ๋ฐ๋์ ๊ฐ์ฒด์ฌ์ผํฉ๋๋ค. state๋ฅผ ์ง์ ๋ณ๊ฒฝํ์ง ๋ง์ธ์. state๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ฉด ์ state๋ก setState๋ฅผ ํธ์ถํ์ธ์.
class Counter extends Component {
state = {
age: 42,
};
handleAgeChange = () => {
this.setState({
age: this.state.age + 1
});
};
render() {
return (
<>
<button onClick={this.handleAgeChange}>
Increment age
</button>
<p>You are {this.state.age}.</p>
</>
);
}
}constructor(props)
ํด๋์ค ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ(ํ๋ฉด์ ์ถ๊ฐ๋จ)๋๊ธฐ ์ ์ constructor๊ฐ ์คํ๋ฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก constructor๋ React์์ ๋ ๊ฐ์ง ๋ชฉ์ ์ผ๋ก๋ง ์ฌ์ฉ๋ฉ๋๋ค. state๋ฅผ ์ ์ธํ๊ณ class ๋ฉ์๋๋ฅผ class ์ธ์คํด์ค์ ๋ฐ์ธ๋ฉํ ์ ์์ต๋๋ค.
class Counter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// ...
}์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ค๋ฉด constructor๋ ๊ฑฐ์ ํ์ํ์ง ์์ต๋๋ค. ๋์ ์ต์ ๋ธ๋ผ์ฐ์ ์ Babel๊ณผ ๊ฐ์ ๋๊ตฌ์์ ๋ชจ๋ ์ง์๋๋ ๊ณต์ฉ class ํ๋ ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ์์ ์ฝ๋๋ฅผ ๋ค์ ์์ฑํ ์ ์์ต๋๋ค.
class Counter extends Component {
state = { counter: 0 };
handleClick = () => {
// ...
}constructor๋ ๋ถ์ ํจ๊ณผ ๋๋ ๊ตฌ๋ ์ ํฌํจํ๋ฉด ์๋ฉ๋๋ค.
๋งค๊ฐ๋ณ์
props: ์ปดํฌ๋ํธ์ ์ด๊ธฐ props.
๋ฐํ๊ฐ
constructor๋ ์๋ฌด๊ฒ๋ ๋ฐํํ๋ฉด ์ ๋ฉ๋๋ค.
์ฃผ์์ฌํญ
-
constructor์์ ๋ถ์ ํจ๊ณผ ๋๋ ๊ตฌ๋ ์ ์คํํ์ง ๋ง์ธ์. ๋์
componentDidMount๋ฅผ ์ฌ์ฉํ์ธ์. -
constructor ๋ด๋ถ์์๋ ๋ค๋ฅธ ๋ช ๋ น์ด๋ณด๋ค
super(props)๋ฅผ ๋จผ์ ํธ์ถํด์ผ ํฉ๋๋ค. ๊ทธ๋ ๊ฒ ํ์ง ์์ผ๋ฉด, constructor๊ฐ ์คํ๋๋ ๋์this.props๋undefined๊ฐ ๋์ด ํผ๋์ค๋ฝ๊ณ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. -
constructor๋
this.state๋ฅผ ์ง์ ํ ๋นํ ์ ์๋ ์ ์ผํ ์์น์ ๋๋ค. ๋ค๋ฅธ ๋ชจ๋ ๋ฉ์๋์์๋this.setState()๋ฅผ ๋์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. constructor์์ setState๋ฅผ ํธ์ถํ์ง ๋ง์ญ์์ค. -
์๋ฒ ๋ ๋๋ง์ ์ฌ์ฉํ ๋, constructor๋ ์๋ฒ์์ ์ญ์ ์คํ๋๊ณ , ๋ค์ด์ด
render๋ฉ์๋๋ ์คํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋componentDidMount๋๋componentWillUnmount์ ๊ฐ์ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ ์๋ฒ์์ ์คํ๋์ง ์์ต๋๋ค. -
Strict ๋ชจ๋๊ฐ ์ค์ ๋๋ฉด React๋ ๊ฐ๋ฐ ์ค์ธ
constructor๋ฅผ ๋ ๋ฒ ํธ์ถํ ๋ค์ ์ธ์คํด์ค ์ค ํ๋๋ฅผ ์ญ์ ํฉ๋๋ค. ์ด๋ฅผ ํตํดconstructor์ธ๋ถ๋ก ์ฎ๊ฒจ์ ธ์ผ ํ๋ ์ฐ๋ฐ์ ์ธ ๋ถ์ ํจ๊ณผ๋ฅผ ํ์ ํ ์ ์์ต๋๋ค.
componentDidCatch(error, info)
componentDidCatch๋ฅผ ์ ์ํ๋ฉด, ์ผ๋ถ ์์ ์ปดํฌ๋ํธ(๋จผ ์์์ ํฌํจ)๊ฐ ์๋ฌ๋ฅผ ๋ฐ์์ํฌ ๋ React๊ฐ ์ด๋ฅผ ํธ์ถํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ด์ ์ค์ธ ์๋ฌ ๋ณด๊ณ ์๋น์ค์ ์๋ฌ๋ฅผ ๊ธฐ๋กํ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก, ์๋ฌ์ ๋ํ ์๋ต์ผ๋ก state๋ฅผ ์
๋ฐ์ดํธํ๊ณ ์ฌ์ฉ์์๊ฒ ์๋ฌ ๋ฉ์์ง๋ฅผ ํ์ํ ์ ์๋ static getDerivedStateFromError์ ํจ๊ป ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฐ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ฅผ error boundary๋ผ๊ณ ํฉ๋๋ค.
๋งค๊ฐ๋ณ์
-
error: ๋ฐ์ํ ์๋ฌ์ ๋๋ค. ์ค์ ๋ก, ๋ณดํต์์๋ฌ์ ์ธ์คํด์ค๊ฐ ๋์ง๋ง JavaScript์์ ๋ฌธ์์ด ๋๋null์ ํฌํจํ ์ด๋ค ๊ฐ์ด๋throwํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณด์ฅ๋์ง ์์ต๋๋ค. -
info: ์๋ฌ์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ํฌํจํ๋ ๊ฐ์ฒด์ ๋๋ค. ์ด๊ฒ์componentStackํ๋๋ ๋ชจ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ์ด๋ฆ๊ณผ ์ถ์ฒ ์์น๋ฟ๋ง ์๋๋ผ ์๋ฌ๋ฅผ throwํ ์ปดํฌ๋ํธ์ stack trace์ ํฌํจํฉ๋๋ค. ํ๋ก๋์ ์์, ์ปดํฌ๋ํธ์ ์ด๋ฆ์ ์ต์ํ๋ฉ๋๋ค. ํ๋ก๋์ ์๋ฌ ๋ณด๊ณ ๋ฅผ ์ค์ ํ๋ฉด ์ผ๋ฐ JavaScript ์๋ฌ ์คํ๊ณผ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ์์ค๋งต์ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ์คํ์ ๋์ฝ๋ฉํ ์ ์์ต๋๋ค.
๋ฐํ๊ฐ
componentDidCatch๋ ์๋ฌด๊ฒ๋ ๋ฐํํ๋ฉด ์ ๋ฉ๋๋ค.
์ฃผ์์ฌํญ
-
๊ณผ๊ฑฐ์๋ UI๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ๋์ฒด ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ํ์ํ๊ธฐ ์ํด
setState๋ฅผcomponentDidCatch์์์ ํธ์ถํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด์์ต๋๋ค. ์ด๋static getDerivedStateFromError๋ฅผ ์ ์ํ๊ธฐ ์ํด ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค. -
React์ ํ๋ก๋์ ๊ณผ ๊ฐ๋ฐ ๋น๋๋
componentDidCatch๊ฐ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ด ์ฝ๊ฐ ๋ค๋ฆ ๋๋ค. ๊ฐ๋ฐ์์๋, ์๋ฌ๋window๊น์ง ๋ฒ๋ธ๋ง๋ ๊ฒ์ด๋ฉฐ, ์ด๋window.onerror๋๋window.addEventListener('error', callback)๊ฐcomponentDidCatch์ ์ํด ํ์ง๋ ์๋ฌ๋ฅผ ๊ฐ๋ก์ฑ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋์ ํ๋ก๋์ ์์, ์๋ฌ๋ ๋ฒ๋ธ๋ง๋์ง ์์ ๊ฒ์ด๋ฉฐ, ์ด๋ ์ด๋ค ์์์ ์๋ฌ ํธ๋ค๋ฌ๊ฐcomponentDidCatch์ ์ํด ๋ช ์์ ์ผ๋ก ํ์ง๋์ง ์์ ์๋ฌ๋ง์ ์์ ํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
componentDidMount()
componentDidMount ๋ฉ์๋๋ฅผ ์ ์ํ๋ฉด ๊ตฌ์ฑ ์์๊ฐ ํ๋ฉด์ ์ถ๊ฐ (๋ง์ดํธ) ๋ ๋ React๊ฐ ํธ์ถํฉ๋๋ค. ์ด๊ฒ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์์ํ๊ฑฐ๋, ๊ตฌ๋
์ ์ค์ ํ๊ฑฐ๋, DOM ๋
ธ๋๋ฅผ ์กฐ์ํ๋ ์ผ๋ฐ์ ์ธ ์ฅ์์
๋๋ค.
componentDidMount๋ฅผ ๊ตฌํํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ค๋ฅธ ์๋ช
์ฃผ๊ธฐ ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, componentDidMount๊ฐ ์ผ๋ถ state๋ props๋ฅผ ์ฝ๋ ๊ฒฝ์ฐ ๋ณ๊ฒฝ ์ฌํญ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด componentDidUpdate๋ฅผ ๊ตฌํํ๊ณ componentDidMount๊ฐ ์ํํ๋ ์์
์ ์ ๋ฆฌํ๊ธฐ ์ํด componentWillUnmount๋ ๊ตฌํํด์ผ ํฉ๋๋ค.
class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};
componentDidMount() {
this.setupConnection();
}
componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount() {
this.destroyConnection();
}
// ...
}๋ ๋ง์ ์์๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
componentDidMount๋ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
๋ฐํ๊ฐ
componentDidMount๋ ์๋ฌด๊ฒ๋ ๋ฐํํ๋ฉด ์ ๋ฉ๋๋ค.
์ฃผ์์ฌํญ
-
Strict ๋ชจ๋๊ฐ ์ผ์ ธ ์์ผ๋ฉด ๊ฐ๋ฐ ์ค์ธ React๊ฐ
componentDidMount๋ฅผ ํธ์ถํ ๋ค์componentWillUnmount๋ฅผ ํธ์ถํ๊ณcomponentDidMount๋ฅผ ๋ค์ ํธ์ถํฉ๋๋ค. ์ด๋ฅผ ํตํดcomponentWillUnmount๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ์์๊ฑฐ๋ ๋ก์ง์ดcomponentDidMount๊ฐ ์ํํ๋ ์์ ์ ์์ ํ โ๋ฏธ๋ฌ๋งโํ์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ์ ์ ์์ต๋๋ค. -
componentDidMount์์setState๋ฅผ ์ฆ์ ํธ์ถํ ์ ์์ง๋ง, ๊ฐ๋ฅํ๋ฉด ํผํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ์ด๋ ์ถ๊ฐ ๋ ๋๋ง์ ์ผ์ผํค์ง๋ง ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ ์ ๋ฐ์ดํธํ๊ธฐ ์ ์ ์ผ์ด๋ฉ๋๋ค. ์ด ๊ฒฝ์ฐrender๊ฐ ๋ ๋ฒ ํธ์ถ๋๋๋ผ๋ ์ฌ์ฉ์๋ ์ค๊ฐ state๋ฅผ ๋ณผ ์ ์์ต๋๋ค. ์ด ํจํด์ ์ข ์ข ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๋ฐ์์ํค๋ฏ๋ก ์ฃผ์ํ์ฌ ์ฌ์ฉํ์ญ์์ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐconstructor์์ ์ด๊ธฐ state๋ฅผ ๋์ ํ ๋นํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ฌ์ด๋ ํดํ๊ณผ ๊ฐ์ด ํฌ๊ธฐ๋ ์์น์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๊ฒ์ ๋ ๋๋งํ๊ธฐ ์ ์ DOM ๋ ธ๋๋ฅผ ์ธก์ ํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ ํ์ํ ์ ์์ต๋๋ค.
componentDidUpdate(prevProps, prevState, snapshot?)
componentDidUpdate ๋ฉ์๋๋ฅผ ์ ์ํ๋ฉด ์ปดํฌ๋ํธ๊ฐ ์
๋ฐ์ดํธ๋ props ๋๋ state๋ก ๋ค์ ๋ ๋๋ง๋ ์งํ React๊ฐ ์ด ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ด๊ธฐ ๋ ๋๋ง์ ํธ์ถ๋์ง ์์ต๋๋ค.
์
๋ฐ์ดํธ ํ DOM์ ์กฐ์ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ํ ํ์ฌ props๋ฅผ ์ด์ props์ ๋น๊ตํ๋ ํ ๋คํธ์ํฌ ์์ฒญ์ ์ํํ๋ ์ผ๋ฐ์ ์ธ ์ฅ์์ด๊ธฐ๋ ํฉ๋๋ค(์: props๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ๊ฒฝ์ฐ ๋คํธ์ํฌ ์์ฒญ์ด ํ์ํ์ง ์์ ์ ์์ต๋๋ค). ์ผ๋ฐ์ ์ผ๋ก componentDidMount ๋ฐ componentWillUnmount์ ํจ๊ป ์ฌ์ฉํฉ๋๋ค.
class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};
componentDidMount() {
this.setupConnection();
}
componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount() {
this.destroyConnection();
}
// ...
}๋ ๋ง์ ์์๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
-
prevProps: ์ ๋ฐ์ดํธ ์ด์ ์ props.prevProps์this.props๋ฅผ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ํ์ธํฉ๋๋ค. -
prevState: ์ ๋ฐ์ดํธ ์ state.prevState๋ฅผthis.state์ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ํ์ธํฉ๋๋ค. -
snapshot:getSnapshotBeforeUpdate๋ฅผ ๊ตฌํํ ๊ฒฝ์ฐ,snapshot์๋ ํด๋น ๋ฉ์๋์์ ๋ฐํํ ๊ฐ์ด ํฌํจ๋ฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉดundefined๊ฐ ๋ฉ๋๋ค.
๋ฐํ๊ฐ
componentDidUpdate๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์์ผ ํฉ๋๋ค.
์ฃผ์์ฌํญ
-
shouldComponentUpdate๊ฐ ์ ์๋์ด ์์ผ๋ฉดcomponentDidUpdate๊ฐ ํธ์ถ๋์ง ์๊ณfalse๋ฅผ ๋ฐํํฉ๋๋ค. -
componentDidUpdate๋ด๋ถ์ ๋ก์ง์ ์ผ๋ฐ์ ์ผ๋กthis.props๋ฅผprevProps์ ๋น๊ตํ๊ณthis.state๋ฅผprevState์ ๋น๊ตํ๋ ์กฐ๊ฑด์ผ๋ก ๋ํํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฌดํ ๋ฃจํ๊ฐ ์์ฑ๋ ์ํ์ด ์์ต๋๋ค. -
componentDidUpdate์์setState๋ฅผ ์ฆ์ ํธ์ถํ ์๋ ์์ง๋ง ๊ฐ๋ฅํ๋ฉด ํผํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ์ถ๊ฐ ๋ ๋๋ง์ด ํธ๋ฆฌ๊ฑฐ๋์ง๋ง ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ ์ ๋ฐ์ดํธํ๊ธฐ ์ ์ ๋ฐ์ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ด ๊ฒฝ์ฐrender๊ฐ ๋ ๋ฒ ํธ์ถ๋๋๋ผ๋ ์ฌ์ฉ์์๊ฒ ์ค๊ฐ state๊ฐ ํ์๋์ง ์์ต๋๋ค. ์ด ํจํด์ ์ข ์ข ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ผ์ผํค์ง๋ง ๋๋ฌผ๊ฒ ๋ชจ๋ฌ์ด๋ ํดํ์ฒ๋ผ ํฌ๊ธฐ๋ ์์น์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๊ฒ์ ๋ ๋๋งํ๊ธฐ ์ ์ DOM ๋ ธ๋๋ฅผ ์ธก์ ํด์ผ ํ๋ ๊ฒฝ์ฐ์ ํ์ํ ์ ์์ต๋๋ค.
componentWillMount()
componentWillReceiveProps(nextProps)
componentWillUpdate(nextProps, nextState)
componentWillUnmount()
componentWillUnmount ๋ฉ์๋๋ฅผ ์ ์ํ๋ฉด React๋ ์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์์ ์ ๊ฑฐ (๋ง์ดํธ ํด์ ) ๋๊ธฐ ์ ์ ์ด ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ์ด๋ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ๋ฅผ ์ทจ์ํ๊ฑฐ๋ ๊ตฌ๋
์ ์ ๊ฑฐํ๋ ์ผ๋ฐ์ ์ธ ์ฅ์์
๋๋ค.
componentWillUnmount ๋ด๋ถ์ ๋ก์ง์ componentDidMount ๋ด๋ถ์ ๋ก์ง์ โ๋ฏธ๋ฌ๋งโํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด componentDidMount๊ฐ ๊ตฌ๋
์ ์ค์ ํ๋ฉด componentWillUnmount๋ ํด๋น ๊ตฌ๋
์ ์ ๋ฆฌํด์ผ ํฉ๋๋ค. componentWillUnmount์ ์ ๋ฆฌ ๋ก์ง์ด ์ผ๋ถ props๋ state๋ฅผ ์ฝ๋ ๊ฒฝ์ฐ, ์ผ๋ฐ์ ์ผ๋ก ์ด์ props๋ state์ ํด๋นํ๋ ๋ฆฌ์์ค(์: ๊ตฌ๋
)๋ฅผ ์ ๋ฆฌํ๊ธฐ ์ํด componentDidUpdate๋ ๊ตฌํํด์ผ ํฉ๋๋ค.
class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};
componentDidMount() {
this.setupConnection();
}
componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount() {
this.destroyConnection();
}
// ...
}๋ ๋ง์ ์์๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
componentWillUnmount๋ ์ด๋ค ๋งค๊ฐ๋ณ์๋ ๋ฐ์ง ์์ต๋๋ค.
๋ฐํ๊ฐ
componentWillUnmount๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์์ผ ํฉ๋๋ค.
์ฃผ์์ฌํญ
- Strict ๋ชจ๋๊ฐ ์ผ์ ธ ์์ผ๋ฉด ๊ฐ๋ฐ ์ React๋
componentDidMount๋ฅผ ํธ์ถํ ๋ค์ ์ฆ์componentWillUnmount๋ฅผ ํธ์ถํ ๋ค์componentDidMount๋ฅผ ๋ค์ ํธ์ถํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉดcomponentWillUnmount๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ์์ด๋ฒ๋ ธ๊ฑฐ๋ ๊ทธ ๋ก์ง์ดcomponentDidMount์ ๋์์ ์์ ํ โ๋ฏธ๋ฌ๋งโํ์ง ์๋์ง ํ์ธํ ์ ์์ต๋๋ค.
forceUpdate(callback?)
์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ๋ก ๋ค์ ๋ ๋๋งํฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก๋ ํ์ํ์ง ์์ต๋๋ค. ์ปดํฌ๋ํธ์ render ๋ฉ์๋๊ฐ this.props, this.state ๋๋ this.context์์๋ง ์ฝ๋ ๊ฒฝ์ฐ, ์ปดํฌ๋ํธ ๋ด๋ถ ๋๋ ๋ถ๋ชจ ์ค ํ๋์์ setState๋ฅผ ํธ์ถํ๋ฉด ์๋์ผ๋ก ๋ค์ ๋ ๋๋ง๋ฉ๋๋ค. ํ์ง๋ง ์ปดํฌ๋ํธ์ render ๋ฉ์๋๊ฐ ์ธ๋ถ ๋ฐ์ดํฐ ์์ค๋ก๋ถํฐ ์ง์ ์ฝ์ด์ค๋ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ ์์ค๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์
๋ฐ์ดํธํ๋๋ก React์ ์ง์ํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก forceUpdate๊ฐ ํ ์ ์๋ ์ผ์
๋๋ค.
forceUpdate์ ๋ชจ๋ ์ฌ์ฉ์ ํผํ๊ณ render์์ this.props์ this.state๋ก๋ถํฐ๋ง ์ฝ๋๋ก ํ์ธ์.
๋งค๊ฐ๋ณ์
- optional
callback: ์ง์ ํ ๊ฒฝ์ฐ React๋ ์ ๋ฐ์ดํธ๊ฐ ์ปค๋ฐ๋ ํ ์ฌ์ฉ์๊ฐ ์ ๊ณตํcallback์ ํธ์ถํฉ๋๋ค.
๋ฐํ๊ฐ
forceUpdate๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์ต๋๋ค.
์ฃผ์์ฌํญ
forceUpdate๋ฅผ ํธ์ถํ๋ฉด React๋shouldComponentUpdate๋ฅผ ํธ์ถํ์ง ์๊ณ ๋ค์ ๋ ๋๋งํฉ๋๋ค.
getChildContext()
์ด ์ปดํฌ๋ํธ๊ฐ ์ ๊ณตํ๋ legacy context์ ๋ํ ๊ฐ์ ์ง์ ํ ์ ์์ต๋๋ค.
getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate๋ฅผ ๊ตฌํํ๋ฉด React๊ฐ DOM์ ์
๋ฐ์ดํธํ๊ธฐ ๋ฐ๋ก ์ ์ ํธ์ถํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ปดํฌ๋ํธ๊ฐ ์ ์ฌ์ ์ผ๋ก ๋ณ๊ฒฝ๋๊ธฐ ์ ์ DOM์์ ์ผ๋ถ ์ ๋ณด(์: ์คํฌ๋กค ์์น)๋ฅผ ์บก์ฒํ ์ ์์ต๋๋ค. ์ด ์๋ช
์ฃผ๊ธฐ ๋ฉ์๋๊ฐ ๋ฐํํ๋ ๋ชจ๋ ๊ฐ์ componentDidUpdate์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ ๋ฐ์ดํธ ์ค์ ์คํฌ๋กค ์์น๋ฅผ ์ ์งํด์ผ ํ๋ ์ฑํ ์ค๋ ๋์ ๊ฐ์ UI์์ ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// ๋ชฉ๋ก์ ์ ํญ๋ชฉ์ ์ถ๊ฐํ๊ณ ์๋์?
// ๋์ค์ ์คํฌ๋กค์ ์กฐ์ ํ ์ ์๋๋ก ์คํฌ๋กค ์์น๋ฅผ ์บก์ฒํฉ๋๋ค.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// ์ค๋
์ท ๊ฐ์ด ์์ผ๋ฉด ๋ฐฉ๊ธ ์ ํญ๋ชฉ์ ์ถ๊ฐํ ๊ฒ์
๋๋ค.
// ์ ํญ๋ชฉ์ด ๊ธฐ์กด ํญ๋ชฉ์ ์์ผ ๋ฐ์ผ๋ก ๋ฐ์ด๋ด์ง ์๋๋ก ์คํฌ๋กค์ ์กฐ์ ํฉ๋๋ค.
// (์ฌ๊ธฐ์ ์ค๋
์ท์ getSnapshotBeforeUpdate์์ ๋ฐํ๋ ๊ฐ์
๋๋ค.)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}์์ ์์์์๋ getSnapshotBeforeUpdate์์ ์ง์ scrollHeight ์์ฑ์ ์ฝ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. render, UNSAFE_componentWillReceiveProps ๋๋ UNSAFE_componentWillUpdate๊ฐ ํธ์ถ๋๋ ์์ ๊ณผ React๊ฐ DOM์ ์
๋ฐ์ดํธํ๋ ์์ ์ฌ์ด์ ์ ์ฌ์ ์ธ ์๊ฐ ๊ฐ๊ฒฉ์ด ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ฌ๋ฌ ๋ฉ์๋์์ ์ด(์ญ์ฃผ: scrollHeight)๋ฅผ ์ฝ๋ ๊ฒ์ ์์ ํ์ง ์์ต๋๋ค.
๋งค๊ฐ๋ณ์
-
prevProps: ์ ๋ฐ์ดํธ ์ด์ ์ props.prevProps์this.props๋ฅผ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ํ์ธํฉ๋๋ค. -
prevState: ์ ๋ฐ์ดํธ ์ state.prevState๋ฅผthis.state์ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ํ์ธํฉ๋๋ค.
๋ฐํ๊ฐ
์ํ๋ ์ ํ์ ์ค๋
์ท ๊ฐ ๋๋ null์ ๋ฐํํด์ผ ํฉ๋๋ค. ๋ฐํํ ๊ฐ์ componentDidUpdate์ ์ธ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋ฉ๋๋ค.
์ฃผ์์ฌํญ
shouldComponentUpdate๊ฐ ์ ์๋์ด ์์ผ๋ฉดgetSnapshotBeforeUpdate๊ฐ ํธ์ถ๋์ง ์๊ณfalse๋ฅผ ๋ฐํํฉ๋๋ค.
render()
render ๋ฉ์๋๋ ํด๋์ค ์ปดํฌ๋ํธ์์ ์ ์ผํ๊ฒ ํ์ํ ๋ฉ์๋์
๋๋ค.
render ๋ฉ์๋๋ ํ๋ฉด์ ํ์ํ ๋ด์ฉ์ ์ง์ ํด์ผ ํฉ๋๋ค, ์๋ฅผ ๋ค์ด
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}React๋ ์ธ์ ๋ render๋ฅผ ํธ์ถํ ์ ์์ผ๋ฏ๋ก ํน์ ์๊ฐ์ ์คํ๋๋ค๊ณ ๊ฐ์ ํ๋ฉด ์ ๋ฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก render ๋ฉ์๋๋ JSX๋ฅผ ๋ฐํํด์ผ ํ์ง๋ง ๋ช ๊ฐ์ง (๋ฌธ์์ด๊ณผ ๊ฐ์) ๋ค๋ฅธ ๋ฐํ ์ ํ์ด ์ง์๋ฉ๋๋ค. ๋ฐํ๋ JSX๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด render ๋ฉ์๋๋ this.props, this.state ๋ฐ this.context๋ฅผ ์ฝ์ ์ ์์ต๋๋ค.
render ๋ฉ์๋๋ ์์ ํจ์๋ก ์์ฑํด์ผ ํฉ๋๋ค. ์ฆ, props, state ๋ฐ context๊ฐ ๋์ผํ ๊ฒฝ์ฐ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค. ๋ํ (๊ตฌ๋
์ค์ ๊ณผ ๊ฐ์) ๋ถ์ ํจ๊ณผ๋ฅผ ํฌํจํ๊ฑฐ๋ ๋ธ๋ผ์ฐ์ API์ ์ํธ์์ฉํ๋ฉด ์ ๋ฉ๋๋ค. ๋ถ์ ํจ๊ณผ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ componentDidMount์ ๊ฐ์ ๋ฉ์๋์์ ๋ฐ์ํด์ผ ํฉ๋๋ค.
๋งค๊ฐ๋ณ์
render: ์ด๋ค ๋งค๊ฐ๋ณ์๋ ๋ฐ์ง ์์ต๋๋ค.
๋ฐํ๊ฐ
render๋ ์ ํจํ ๋ชจ๋ React ๋
ธ๋๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ <div />, ๋ฌธ์์ด, ์ซ์, portals, ๋น ๋
ธ๋(null, undefined, true, false) ๋ฐ React ๋
ธ๋์ ๋ฐฐ์ด๊ณผ ๊ฐ์ React ์๋ฆฌ๋จผํธ๊ฐ ํฌํจ๋ฉ๋๋ค.
์ฃผ์์ฌํญ
-
render๋ props, state, context์ ์์ํ ํจ์๋ก ์์ฑ๋์ด์ผ ํฉ๋๋ค. ๋ถ์ ํจ๊ณผ๊ฐ ์์ด์ผ ํฉ๋๋ค. -
shouldComponentUpdate๊ฐ ์ ์๋๊ณfalse๋ฅผ ๋ฐํํ๋ฉดrender๊ฐ ํธ์ถ๋์ง ์์ต๋๋ค. -
Strict ๋ชจ๋๊ฐ ์ผ์ ธ ์์ผ๋ฉด React๋ ๊ฐ๋ฐ ๊ณผ์ ์์
render๋ฅผ ๋ ๋ฒ ํธ์ถํ ๋ค์ ๊ฒฐ๊ณผ ์ค ํ๋๋ฅผ ๋ฒ๋ฆฝ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉดrender๋ฉ์๋์์ ์ ๊ฑฐํด์ผ ํ๋ ์ฐ๋ฐ์ ์ธ ๋ถ์ ํจ๊ณผ๋ฅผ ์์์ฐจ๋ฆด ์ ์์ต๋๋ค. -
renderํธ์ถ๊ณผ ํ์componentDidMount๋๋componentDidUpdateํธ์ถ ์ฌ์ด์๋ ์ผ๋์ผ ๋์์ด ์์ต๋๋ค.renderํธ์ถ ๊ฒฐ๊ณผ ์ค ์ผ๋ถ๋ ์ ์ตํ ๋ React์ ์ํด ๋ฒ๋ ค์ง ์ ์์ต๋๋ค.
setState(nextState, callback?)
setState๋ฅผ ํธ์ถํ์ฌ React ์ปดํฌ๋ํธ์ state๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค.
class Form extends Component {
state = {
name: 'Taylor',
};
handleNameChange = (e) => {
const newName = e.target.value;
this.setState({
name: newName
});
}
render() {
return (
<>
<input value={this.state.name} onChange={this.handleNameChange} />
<p>Hello, {this.state.name}.
</>
);
}
}setState๋ ์ปดํฌ๋ํธ state์ ๋ํ ๋ณ๊ฒฝ ์ฌํญ์ ํ์ ๋ฃ์ต๋๋ค. ์ด ์ปดํฌ๋ํธ์ ๊ทธ ์์์ด ์๋ก์ด state๋ก ๋ค์ ๋ ๋๋งํด์ผ ํ๋ค๋ ๊ฒ์ React์๊ฒ ์๋ ค์ค๋๋ค. ์ด๊ฒ์ด ์ํธ์์ฉ์ ๋ฐ์ํ์ฌ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์
๋ฐ์ดํธํ๋ ์ฃผ์ ๋ฐฉ๋ฒ์
๋๋ค.
setState์ ํจ์๋ฅผ ์ ๋ฌํ ์๋ ์์ต๋๋ค. ์ด ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์ state๋ฅผ ๊ธฐ๋ฐ์ผ๋ก state๋ฅผ ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.
handleIncreaseAge = () => {
this.setState(prevState => {
return {
age: prevState.age + 1
};
});
}์ด ์์ ์ ์ํํ ํ์๋ ์์ง๋ง ๋์ผํ ์ด๋ฒคํธ ์ค์ state๋ฅผ ์ฌ๋ฌ ๋ฒ ์ ๋ฐ์ดํธํ๋ ค๋ ๊ฒฝ์ฐ ์ ์ฉํฉ๋๋ค.
๋งค๊ฐ๋ณ์
-
nextState: ๊ฐ์ฒด ๋๋ ํจ์ ์ค ํ๋์ ๋๋ค.- ๊ฐ์ฒด๋ฅผ
nextState๋ก ์ ๋ฌํ๋ฉดthis.state์ ์๊ฒ(shallowly) ๋ณํฉ๋ฉ๋๋ค. - ํจ์๋ฅผ
nextState๋ก ์ ๋ฌํ๋ฉด ์ ๋ฐ์ดํฐ ํจ์ ๋ก ์ทจ๊ธ๋ฉ๋๋ค. ์ด ํจ์๋ ์์ํด์ผ ํ๊ณ , pending state์ props๋ฅผ ์ธ์๋ก ๋ฐ์์ผ ํ๋ฉฐ,this.state์ ์๊ฒ(shallowly) ๋ณํฉํ ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค. React๋ ์ ๋ฐ์ดํฐ ํจ์๋ฅผ ํ์ ๋ฃ๊ณ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํฉ๋๋ค. ๋ค์ ๋ ๋๋ง ์ค์ React๋ ํ์ ์๋ ๋ชจ๋ ์ ๋ฐ์ดํฐ๋ฅผ ์ด์ state์ ์ ์ฉํ์ฌ ๋ค์ state๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- ๊ฐ์ฒด๋ฅผ
-
optional
callback: ์ง์ ํ ๊ฒฝ์ฐ React๋ ์ ๋ฐ์ดํธ๊ฐ ์ปค๋ฐ๋ ํ ์ฌ์ฉ์๊ฐ ์ ๊ณตํcallback์ ํธ์ถํฉ๋๋ค.
๋ฐํ๊ฐ
setState๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์ต๋๋ค.
์ฃผ์์ฌํญ
-
setState๋ฅผ ์ปดํฌ๋ํธ๋ฅผ ์ ๋ฐ์ดํธํ๋ ์ฆ๊ฐ์ ์ธ ๋ช ๋ น์ด ์๋ ์์ฒญ์ผ๋ก ์๊ฐํ์ธ์. ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ์ด๋ฒคํธ์ ๋ฐ์ํ์ฌ state๋ฅผ ์ ๋ฐ์ดํธํ๋ฉด React๋ ์ ๋ฐ์ดํธ๋ฅผ batchํ๊ณ ์ด๋ฒคํธ๊ฐ ๋๋ ๋ ๋จ์ผ ํจ์ค๋ก ํจ๊ป ๋ค์ ๋ ๋๋งํฉ๋๋ค. ๋๋ฌผ๊ฒ ํน์ state ์ ๋ฐ์ดํธ๋ฅผ ๊ฐ์ ๋ก ๋๊ธฐํํ์ฌ ์ ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ,flushSync๋ก ๋ํํ ์ ์์ง๋ง, ์ด ๊ฒฝ์ฐ ์ฑ๋ฅ์ด ์ ํ๋ ์ ์์ต๋๋ค. -
setState๋this.state๋ฅผ ์ฆ์ ์ ๋ฐ์ดํธํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์setState๋ฅผ ํธ์ถํ ์งํthis.state๋ฅผ ์ฝ๋ ๊ฒ์ ์ ์ฌ์ ์ธ ์ํ์ด ๋ ์ ์์ต๋๋ค. ๋์ , ์ ๋ฐ์ดํธ๊ฐ ์ ์ฉ๋ ํ์ ์คํ๋๋๋ก ๋ณด์ฅ๋๋componentDidUpdate๋๋ setStatecallback์ธ์๋ฅผ ์ฌ์ฉํ์ญ์์ค. ์ด์ state๋ฅผ ๊ธฐ๋ฐ์ผ๋ก state๋ฅผ ์ค์ ํด์ผ ํ๋ ๊ฒฝ์ฐ ์์์ ์ค๋ช ํ ๋๋ก ํจ์๋ฅผnextState์ ์ ๋ฌํ ์ ์์ต๋๋ค.
shouldComponentUpdate(nextProps, nextState, nextContext)
shouldComponentUpdate๋ฅผ ์ ์ํ๋ฉด React๊ฐ ์ด๋ฅผ ํธ์ถํ์ฌ ์ฌ๋ ๋๋ง์ ๊ฑด๋๋ธ ์ ์๋์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
์ง์ ์์ฑ์ ์ํ๋ ๊ฒ์ด ํ์คํ๋ค๋ฉด, this.props๋ฅผ nextProps์, this.state๋ฅผ nextState์ ๋น๊ตํ๊ณ false๋ฅผ ๋ฐํํ์ฌ React์ ์
๋ฐ์ดํธ๋ฅผ ๊ฑด๋๋ธ ์ ์์์ ์๋ฆด ์ ์์ต๋๋ค.
class Rectangle extends Component {
state = {
isHovered: false
};
shouldComponentUpdate(nextProps, nextState) {
if (
nextProps.position.x === this.props.position.x &&
nextProps.position.y === this.props.position.y &&
nextProps.size.width === this.props.size.width &&
nextProps.size.height === this.props.size.height &&
nextState.isHovered === this.state.isHovered
) {
// ๋ณ๊ฒฝ๋ ์ฌํญ์ด ์์ผ๋ฏ๋ก ๋ค์ ๋ ๋๋งํ ํ์๊ฐ ์์ต๋๋ค.
return false;
}
return true;
}
// ...
}์๋ก์ด props๋ state๊ฐ ์์ ๋๋ฉด ๋ ๋๋งํ๊ธฐ ์ ์ React๊ฐ shouldComponentUpdate๋ฅผ ํธ์ถํฉ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ true์
๋๋ค. ์ด ๋ฉ์๋๋ ์ด๊ธฐ ๋ ๋๋ง์ด๋ forceUpdate๊ฐ ์ฌ์ฉ๋ ๋๋ ํธ์ถ๋์ง ์์ต๋๋ค.
๋งค๊ฐ๋ณ์
nextProps: ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋งํ ๋ค์ props์ ๋๋ค.nextProps์this.props๋ฅผ ๋น๊ตํ์ฌ ๋ฌด์์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํฉ๋๋ค.nextState: ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋งํ ๋ค์ state์ ๋๋ค.nextState์this.state๋ฅผ ๋น๊ตํ์ฌ ๋ฌด์์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํฉ๋๋ค.nextContext: ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋งํ ๋ค์ context์ ๋๋ค.nextContext๋ฅผthis.context์ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ํ์ธํฉ๋๋ค.static contextType(modern) ๋๋static contextTypes(legacy)๋ฅผ ์ง์ ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฐํ๊ฐ
์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํ๋ ค๋ฉด true๋ฅผ ๋ฐํํฉ๋๋ค. ์ด๊ฒ์ด ๊ธฐ๋ณธ ๋์์
๋๋ค.
React์ ์ฌ๋ ๋๋ง์ ๊ฑด๋๋ธ ์ ์์์ ์๋ฆฌ๋ ค๋ฉด false๋ฅผ ๋ฐํํฉ๋๋ค.
์ฃผ์์ฌํญ
-
์ด ๋ฉ์๋๋ ์ค์ง ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด์๋ง ์กด์ฌํฉ๋๋ค. ์ด ๋ฉ์๋ ์์ด ์ปดํฌ๋ํธ๊ฐ ์ค๋จ๋๋ ๊ฒฝ์ฐ ๋จผ์ ๊ทธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ธ์.
-
shouldComponentUpdate๋ฅผ ์ง์ ์์ฑํ๋ ๋์PureComponent๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.PureComponent๋ props์ state๋ฅผ ์๊ฒ(shallowly) ๋น๊ตํ์ฌ ํ์ํ ์ ๋ฐ์ดํธ๋ฅผ ๊ฑด๋๋ธ ๊ฐ๋ฅ์ฑ์ ์ค์ฌ์ค๋๋ค. -
shouldComponentUpdate์์ ์์ ์ผ์น(deep equality) ๊ฒ์ฌ๋ฅผ ํ๊ฑฐ๋JSON.stringify๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ต๋๋ค. ์ด๋ ์ฑ๋ฅ์ ์์ธกํ ์ ์๊ณ ๋ชจ๋ prop๊ณผ state์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์์กด์ ์ด๊ฒ ํฉ๋๋ค. ์ต์์ ๊ฒฝ์ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ช ์ด์ฉ ๋ฉ์ถ๋ ํ์์ด ๋ฐ์ํ๊ณ ์ต์ ์ ๊ฒฝ์ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ถฉ๋ํ ์ํ์ด ์์ต๋๋ค. -
false๋ฅผ ๋ฐํํด๋ ์์ ์ปดํฌ๋ํธ๋ค์์ ๊ทธ๋ค์ state๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ค์ ๋ ๋๋ง๋๋ ๊ฒ์ ๋ง์ง๋ ๋ชปํฉ๋๋ค. -
false๋ฅผ ๋ฐํํ๋ค๊ณ ํด์ ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋ ๋๋ง๋์ง ์๋๋ค๋ ๋ณด์ฅ์ ์์ต๋๋ค. React๋ ๋ฐํ๊ฐ์ ํํธ๋ก ์ฌ์ฉํ์ง๋ง ๋ค๋ฅธ ์ด์ ๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ผ ๊ฒฝ์ฐ ์ฌ์ ํ ๋ ๋๋ง์ ์ ํํ ์ ์์ต๋๋ค.
UNSAFE_componentWillMount()
UNSAFE_componentWillMount๋ฅผ ์ ์ํ๋ฉด React๋ constructor ๋ฐ๋ก ๋ค์ ์ด๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ญ์ฌ์ ์ธ ์ด์ ๋ก๋ง ์กด์ฌํ๋ฉฐ ์๋ก์ด ์ฝ๋์์ ์ฌ์ฉํ๋ฉด ์ ๋ฉ๋๋ค. ๋์ ๋ค๋ฅธ ๋์์ ์ฌ์ฉํ์ธ์.
- state๋ฅผ ์ด๊ธฐํํ๋ ค๋ฉด
state๋ฅผ class ํ๋๋ก ์ ์ธํ๊ฑฐ๋constructor๋ด์์this.state๋ฅผ ์ค์ ํ์ธ์. - ๋ถ์ ํจ๊ณผ๋ฅผ ์คํํ๊ฑฐ๋ ๊ตฌ๋
์ ์ค์ ํด์ผ ํ๋ ๊ฒฝ์ฐ ํด๋น ๋ก์ง์
componentDidMount๋ก ์ฎ๊ธฐ์ธ์.
์์ ํ์ง ์์ ์๋ช ์ฃผ๊ธฐ์์ ๋ฒ์ด๋ ๋ง์ด๊ทธ๋ ์ด์ ํ ์ฌ๋ก๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
UNSAFE_componentWillMount๋ ์ด๋ ํ ๋งค๊ฐ๋ณ์๋ ๋ฐ์ง ์์ต๋๋ค.
๋ฐํ๊ฐ
UNSAFE_componentWillMount๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์์ผ ํฉ๋๋ค.
์ฃผ์์ฌํญ
-
์ปดํฌ๋ํธ๊ฐ
static getDerivedStateFromProps๋๋getSnapshotBeforeUpdate๋ฅผ ๊ตฌํํ๋ ๊ฒฝ์ฐUNSAFE_componentWillMount๊ฐ ํธ์ถ๋์ง ์์ต๋๋ค. -
์ด๋ฆ๊ณผ๋ ๋ฌ๋ฆฌ, ์ฑ์ด
Suspense์ ๊ฐ์ ์ต์ React ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐUNSAFE_componentWillMount๋ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๊ฒ์ ๋ณด์ฅํ์ง ์์ต๋๋ค. ๋ ๋๋ง ์๋๊ฐ ์ผ์ ์ค๋จ๋๋ฉด(์๋ฅผ ๋ค์ด ์ผ๋ถ ์์ ์ปดํฌ๋ํธ์ ์ฝ๋๊ฐ ์์ง ๋ก๋๋์ง ์์๊ธฐ ๋๋ฌธ์) React๋ ์งํ ์ค์ธ ํธ๋ฆฌ๋ฅผ ๋ฒ๋ฆฌ๊ณ ๋ค์ ์๋์์ ์ปดํฌ๋ํธ๋ฅผ ์ฒ์๋ถํฐ ๊ตฌ์ฑํ๋ ค๊ณ ์๋ํฉ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ์ด ๋ฉ์๋๊ฐ โ์์ ํ์ง ์์โ ์ด์ ์ ๋๋ค. ๋ง์ดํ ์ ์์กดํ๋ ์ฝ๋(์: ๊ตฌ๋ ์ถ๊ฐ)๋componentDidMount๋ก ์ด๋ํด์ผ ํฉ๋๋ค. -
UNSAFE_componentWillMount๋ ์๋ฒ ๋ ๋๋ง ์ค์ ์คํ๋๋ ์ ์ผํ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋์ ๋๋ค. ๋ชจ๋ ์ค์ฉ์ ์ธ ์ฉ๋๋ก ๋ณผ ๋constructor์ ๋์ผํ๋ฏ๋ก ์ด๋ฌํ ์ ํ์ ๋ก์ง์๋constructor๋ฅผ ๋์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
UNSAFE_componentWillReceiveProps๋ฅผ ์ ์ํ๋ฉด ์ปดํฌ๋ํธ๊ฐ ์๋ก์ด props๋ฅผ ์์ ํ ๋ React๊ฐ ์ด๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ญ์ฌ์ ์ธ ์ด์ ๋ก๋ง ์กด์ฌํ๋ฉฐ ์๋ก์ด ์ฝ๋์์ ์ฌ์ฉํ๋ฉด ์ ๋ฉ๋๋ค. ๋์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ธ์.
- props ๋ณ๊ฒฝ์ ๋ํ ์๋ต์ผ๋ก ๋ถ์ ํจ๊ณผ๋ฅผ ์คํ(์: ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ, ์ ๋๋ฉ์ด์
์คํ, ๊ตฌ๋
์ฌ์ด๊ธฐํ)ํด์ผ ํ๋ ๊ฒฝ์ฐ ํด๋น ๋ก์ง์
componentDidUpdate๋ก ์ฎ๊ธฐ์ธ์. - props๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์ผ๋ถ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ณ์ฐํ์ง ์์์ผ ํ๋ ๊ฒฝ์ฐ ๋์ memoization helper๋ฅผ ์ฌ์ฉํ์ธ์.
- props๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ผ๋ถ state๋ฅผ โ์ด๊ธฐํโ ํด์ผ ํ๋ ๊ฒฝ์ฐ, ์ปดํฌ๋ํธ๋ฅผ ์์ ํ ์ ์ดํ๊ฑฐ๋ key๋ก ์์ ํ ์ ์ดํ์ง ์๋๋ก ๋ง๋๋ ๊ฒ์ด ์ข์ต๋๋ค.
- props๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ผ๋ถ state๋ฅผ โ์กฐ์ โ ํด์ผ ํ๋ ๊ฒฝ์ฐ ๋ ๋๋ง ์ค์ props๋ง์ผ๋ก ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ๊ณ์ฐํ ์ ์๋์ง ํ์ธํ์ธ์. ๊ณ์ฐํ ์ ์๋ ๊ฒฝ์ฐ
static getDerivedStateFromProps๋ฅผ ๋์ ์ฌ์ฉํ์ธ์.
์์ ํ์ง ์์ ์๋ช ์ฃผ๊ธฐ์์ ๋ฒ์ด๋ ๋ง์ด๊ทธ๋ ์ด์ ํ ์ฌ๋ก๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
nextProps: ์ปดํฌ๋ํธ๊ฐ ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ก๋ถํฐ ๋ฐ์ผ๋ ค๋ ๋ค์ props์ ๋๋ค.nextProps์this.props๋ฅผ ๋น๊ตํ์ฌ ๋ฌด์์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํฉ๋๋ค.nextContext: ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ณต๊ธ์(provider)๋ก๋ถํฐ ๋ฐ์ผ๋ ค๋ ๋ค์ props์ ๋๋ค.nextContext๋ฅผthis.context์ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ํ์ธํฉ๋๋ค.static contextType(modern) ๋๋static contextTypes(legacy)๋ฅผ ์ง์ ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฐํ๊ฐ
UNSAFE_componentWillReceiveProps๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์์ผ ํฉ๋๋ค.
์ฃผ์์ฌํญ
-
์ปดํฌ๋ํธ๊ฐ
static getDerivedStateFromProps๋๋getSnapshotBeforeUpdate๋ฅผ ๊ตฌํํ๋ ๊ฒฝ์ฐUNSAFE_componentWillReceiveProps๊ฐ ํธ์ถ๋์ง ์์ต๋๋ค. -
์ด๋ฆ๊ณผ๋ ๋ฌ๋ฆฌ, ์ฑ์ด
Suspense์ ๊ฐ์ ์ต์ React ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐUNSAFE_componentWillReceiveProps๋ ์ปดํฌ๋ํธ๊ฐ ํด๋น props๋ฅผ ์์ ํ ๊ฒ์ ๋ณด์ฅํ์ง ์์ต๋๋ค. ๋ ๋๋ง ์๋๊ฐ ์ผ์ ์ค๋จ๋๋ฉด(์๋ฅผ ๋ค์ด ์ผ๋ถ ์์ ์ปดํฌ๋ํธ์ ์ฝ๋๊ฐ ์์ง ๋ก๋๋์ง ์์๊ธฐ ๋๋ฌธ์) React๋ ์งํ ์ค์ธ ํธ๋ฆฌ๋ฅผ ๋ฒ๋ฆฌ๊ณ ๋ค์ ์๋ ์ค์ ์ปดํฌ๋ํธ๋ฅผ ์ฒ์๋ถํฐ ๋ค์ ๊ตฌ์ฑํ๋ ค๊ณ ์๋ํฉ๋๋ค. ๋ค์ ๋ ๋๋ง์ ์๋ํ ๋์ฏค์ด๋ฉด props๊ฐ ๋ฌ๋ผ์ ธ ์์ ์ ์์ต๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ์ด ๋ฉ์๋๊ฐ โ์์ ํ์ง ์์โ ์ด์ ์ ๋๋ค. ์ปค๋ฐ๋ ์ ๋ฐ์ดํธ์ ๋ํด์๋ง ์คํ๋์ด์ผ ํ๋ ์ฝ๋(์: ๊ตฌ๋ ์ฌ์ค์ )๋componentDidUpdate๋ก ์ด๋ํด์ผ ํฉ๋๋ค. -
UNSAFE_componentWillReceiveProps๋ ์ปดํฌ๋ํธ๊ฐ ์ง๋๋ฒ๊ณผ ๋ค๋ฅธ props๋ฅผ ๋ฐ์๋ค๋ ๊ฒ์ ์๋ฏธํ์ง ์์ต๋๋ค.nextProps์this.props๋ฅผ ์ง์ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ์ฌํญ์ด ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค. -
React๋ ๋ง์ดํธํ๋ ๋์ ์ด๊ธฐ props์ ํจ๊ป
UNSAFE_componentWillReceiveProps๋ฅผ ํธ์ถํ์ง ์์ต๋๋ค. ์ปดํฌ๋ํธ์ ์ผ๋ถ props๊ฐ ์ ๋ฐ์ดํธ๋ ๊ฒฝ์ฐ์๋ง ์ด ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ ์ปดํฌ๋ํธ ๋ด๋ถ์์setState๋ฅผ ํธ์ถํด๋UNSAFE_componentWillReceiveProps๊ฐ ํธ๋ฆฌ๊ฑฐ๋์ง ์์ต๋๋ค.
UNSAFE_componentWillUpdate(nextProps, nextState)
UNSAFE_componentWillUpdate๋ฅผ ์ ์ํ๋ฉด React๋ ์ props๋ state๋ก ๋ ๋๋งํ๊ธฐ ์ ์ ์ด๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ญ์ฌ์ ์ธ ์ด์ ๋ก๋ง ์กด์ฌํ๋ฉฐ ์๋ก์ด ์ฝ๋์์ ์ฌ์ฉํ๋ฉด ์ ๋ฉ๋๋ค. ๋์ ๋ค๋ฅธ ๋์์ ์ฌ์ฉํ์ธ์.
- props๋ state ๋ณ๊ฒฝ์ ๋ํ ์๋ต์ผ๋ก ๋ถ์ ํจ๊ณผ(์: ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ, ์ ๋๋ฉ์ด์
์คํ, ๊ตฌ๋
์ฌ์ด๊ธฐํ)๋ฅผ ์คํํด์ผ ํ๋ ๊ฒฝ์ฐ, ํด๋น ๋ก์ง์
componentDidUpdate๋ก ์ด๋ํ์ธ์. - ๋์ค์
componentDidUpdate์์ ์ฌ์ฉํ ์ ์๋๋ก DOM์์ ์ผ๋ถ ์ ๋ณด(์: ํ์ฌ ์คํฌ๋กค ์์น๋ฅผ ์ ์ฅํ๊ธฐ ์ํด)๋ฅผ ์ฝ์ด์ผ ํ๋ ๊ฒฝ์ฐ, ๋์getSnapshotBeforeUpdate๋ด๋ถ์์ ์ฝ์ต๋๋ค.
์์ ํ์ง ์์ ์๋ช ์ฃผ๊ธฐ์์ ๋ฒ์ด๋ ๋ง์ด๊ทธ๋ ์ด์ ํ ์ฌ๋ก๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
nextProps: ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋งํ ๋ค์ props์ ๋๋ค.nextProps์this.props๋ฅผ ๋น๊ตํ์ฌ ๋ฌด์์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํฉ๋๋ค.nextState: ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋งํ ๋ค์ state์ ๋๋ค.nextState์this.state๋ฅผ ๋น๊ตํ์ฌ ๋ฌด์์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํฉ๋๋ค.
๋ฐํ๊ฐ
UNSAFE_componentWillUpdate๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์์ผ ํฉ๋๋ค.
์ฃผ์์ฌํญ
-
shouldComponentUpdate๊ฐ ์ ์๋ ๊ฒฝ์ฐUNSAFE_componentWillUpdate๋ ํธ์ถ๋์ง ์์ผ๋ฉฐfalse๋ฅผ ๋ฐํํฉ๋๋ค. -
์ปดํฌ๋ํธ๊ฐ
static getDerivedStateFromProps๋๋getSnapshotBeforeUpdate๋ฅผ ๊ตฌํํ๋ ๊ฒฝ์ฐUNSAFE_componentWillUpdate๊ฐ ํธ์ถ๋์ง ์์ต๋๋ค. -
componentWillUpdate์ค์setState๋ฅผ ํธ์ถํ๋ ๊ฒ(๋๋ Redux ์ก์ ์ dispatchํ๋ ๊ฒ๊ณผ ๊ฐ์ดsetState๊ฐ ํธ์ถ๋๋๋ก ํ๋ ๋ชจ๋ ๋ฉ์๋)์ ์ง์๋์ง ์์ต๋๋ค. -
์ด๋ฆ๊ณผ๋ ๋ฌ๋ฆฌ, ์ฑ์ด
Suspense์ ๊ฐ์ ์ต์ React ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐUNSAFE_componentWillUpdate๋ ์ปดํฌ๋ํธ๊ฐ ์ ๋ฐ์ดํธ๋ ๊ฒ์ ๋ณด์ฅํ์ง๋ ์์ต๋๋ค. ๋ ๋๋ง ์๋๊ฐ ์ผ์ ์ค๋จ๋๋ฉด(์๋ฅผ ๋ค์ด ์ผ๋ถ ํ์ ์ปดํฌ๋ํธ์ ์ฝ๋๊ฐ ์์ง ๋ก๋๋์ง ์์๊ธฐ ๋๋ฌธ์) React๋ ์งํ ์ค์ธ ํธ๋ฆฌ๋ฅผ ๋ฒ๋ฆฌ๊ณ ๋ค์ ์๋์์ ์ปดํฌ๋ํธ๋ฅผ ์ฒ์๋ถํฐ ์๋ก ๊ตฌ์ฑํ๋ ค๊ณ ์๋ํฉ๋๋ค. ๋ค์ ๋ ๋๋ง ์๋ ์์๋ props์ state๊ฐ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ์ด ๋ฉ์๋๊ฐ โ์์ ํ์ง ์์โ ์ด์ ์ ๋๋ค. ์ปค๋ฐ๋ ์ ๋ฐ์ดํธ์ ๋ํด์๋ง ์คํ๋์ด์ผ ํ๋ ์ฝ๋(์: ๊ตฌ๋ ์ฌ์ค์ )๋componentDidUpdate๋ก ์ด๋ํด์ผ ํฉ๋๋ค. -
UNSAFE_componentWillUpdate๋ ์ปดํฌ๋ํธ๊ฐ ์ง๋๋ฒ๊ณผ ๋ค๋ฅธ props๋ state๋ฅผ ๋ฐ์๋ค๋ ๊ฒ์ ์๋ฏธํ์ง ์์ต๋๋ค.nextProps๋ฅผthis.props์,nextState๋ฅผthis.state์ ์ง์ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ์ฌํญ์ด ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค. -
React๋ ๋ง์ดํธํ๋ ๋์ ์ด๊ธฐ props์ state์ ํจ๊ป
UNSAFE_componentWillUpdate๋ฅผ ํธ์ถํ์ง ์์ต๋๋ค.
static childContextTypes
์ด ์ปดํฌ๋ํธ๊ฐ ์ ๊ณตํ๋ legacy context๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
static contextTypes
์ด ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉํ legacy context๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
static contextType
ํด๋์ค ์ปดํฌ๋ํธ์์ this.context ๋ฅผ ์ฝ์ผ๋ ค๋ฉด ์ฝ์ด์ผ ํ๋ context๋ฅผ ์ง์ ํด์ผ ํฉ๋๋ค. static contextType์ผ๋ก ์ง์ ํ๋ context๋ ์ด์ ์ createContext๋ก ์์ฑํ ๊ฐ์ด์ด์ผ ํฉ๋๋ค.
class Button extends Component {
static contextType = ThemeContext;
render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}static defaultProps
static defaultProps๋ฅผ ์ ์ํ์ฌ class์ ๊ธฐ๋ณธ props์ ์ค์ ํ ์ ์์ต๋๋ค. undefined์ ๋๋ฝ๋ props์๋ ์ฌ์ฉ๋์ง๋ง null props์๋ ์ฌ์ฉ๋์ง ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, color prop์ ๊ธฐ๋ณธ๊ฐ์ 'blue'๋ก ์ ์ํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
class Button extends Component {
static defaultProps = {
color: 'blue'
};
render() {
return <button className={this.props.color}>click me</button>;
}
}color props์ด ์ ๊ณต๋์ง ์๊ฑฐ๋ undefined์ธ ๊ฒฝ์ฐ ๊ธฐ๋ณธ์ ์ผ๋ก โblue'๋ก ์ค์ ๋ฉ๋๋ค.
<>
{/* this.props.color is "blue" */}
<Button />
{/* this.props.color is "blue" */}
<Button color={undefined} />
{/* this.props.color is null */}
<Button color={null} />
{/* this.props.color is "red" */}
<Button color="red" />
</>static propTypes
prop-types ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํจ๊ป static propTypes๋ฅผ ์ ์ํ์ฌ ์ปดํฌ๋ํธ์์ ํ์ฉ๋๋ props์ ์ ํ์ ์ ์ธํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ ํ์ ๋ ๋๋ง ์ค๊ณผ ๊ฐ๋ฐ ์ค์๋ง ํ์ธ๋ฉ๋๋ค.
import PropTypes from 'prop-types';
class Greeting extends React.Component {
static propTypes = {
name: PropTypes.string
};
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}static getDerivedStateFromError(error)
static getDerivedStateFromError๋ฅผ ์ ์ํ๋ฉด ๋ ๋๋ง ๋์ค ์์ ์ปดํฌ๋ํธ(๋ฉ๋ฆฌ ๋จ์ด์ง ์์ ํฌํจ)๊ฐ ์๋ฌ๋ฅผ throw ํ ๋ React๊ฐ ์ด๋ฅผ ํธ์ถํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด UI๋ฅผ ์ง์ฐ๋ ๋์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ผ๋ถ ๋ถ์ ์๋น์ค์ ์ค๋ฅ ๋ณด๊ณ ์๋ฅผ ๋ณด๋ผ ์ ์๋ componentDidCatch์ ํจ๊ป ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฌํ ๋ฉ์๋๊ฐ ์๋ ์ปดํฌ๋ํธ๋ฅผ error boundary ๋ผ๊ณ ํฉ๋๋ค.
๋งค๊ฐ๋ณ์
error: throw ๋ ์ค๋ฅ์ ๋๋ค. ์ค์ ๋ก๋ ์ผ๋ฐ์ ์ผ๋กError์ ์ธ์คํด์ค๊ฐ ๋์ง๋ง, ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ๋ฌธ์์ด์ด๋ ์ฌ์ง์ดnull์ ํฌํจํ ๋ชจ๋ ๊ฐ์throwํ ์ ์์ผ๋ฏ๋ก ๋ณด์ฅ๋์ง๋ ์์ต๋๋ค.
๋ฐํ๊ฐ
static getDerivedStateFromError๋ ์ปดํฌ๋ํธ์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ๋๋ก ์ง์ํ๋ state๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค.
์ฃผ์์ฌํญ
static getDerivedStateFromError๋ ์์ ํจ์์ฌ์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ถ์ ์๋น์ค๋ฅผ ํธ์ถํ๋ ๋ฑ์ ๋ถ์ ํจ๊ณผ๋ฅผ ์ํํ๋ ค๋ฉดcomponentDidCatch๋ ๊ตฌํํด์ผ ํฉ๋๋ค.
static getDerivedStateFromProps(props, state)
static getDerivedStateFromProps๋ฅผ ์ ์ํ๋ฉด React๋ ์ด๊ธฐ ๋ง์ดํธ ๋ฐ ํ์ ์
๋ฐ์ดํธ ๋ชจ๋์์ render๋ฅผ ํธ์ถํ๊ธฐ ๋ฐ๋ก ์ ์ ์ด๋ฅผ ํธ์ถํฉ๋๋ค. state๋ฅผ ์
๋ฐ์ดํธํ๋ ค๋ฉด ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ณ , ์๋ฌด๊ฒ๋ ์
๋ฐ์ดํธํ์ง ์์ผ๋ ค๋ฉด null์ ๋ฐํํด์ผ ํฉ๋๋ค.
์ด ๋ฉ์๋๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ props์ ๋ณ๊ฒฝ์ ๋ฐ๋ผ state๊ฐ ๋ฌ๋ผ์ง๋ ๋๋ฌธ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ํด ์กด์ฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ด Form ์ปดํฌ๋ํธ๋ userId props๊ฐ ๋ณ๊ฒฝ๋๋ฉด email state๋ฅผ ์ฌ์ค์ ํฉ๋๋ค.
class Form extends Component {
state = {
email: this.props.defaultEmail,
prevUserID: this.props.userID
};
static getDerivedStateFromProps(props, state) {
// ํ์ฌ ์ฌ์ฉ์๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค,
// ํด๋น ์ฌ์ฉ์์ ์ฐ๊ฒฐ๋ state์ ๋ชจ๋ ๋ถ๋ถ์ ์ฌ์ค์ ํฉ๋๋ค.
// ์ด ๊ฐ๋จํ ์์ ์์๋ ์ด๋ฉ์ผ๋ง ํด๋น๋ฉ๋๋ค.
if (props.userID !== state.prevUserID) {
return {
prevUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}
// ...
}์ด ํจํด์ ์ฌ์ฉํ๋ ค๋ฉด props์ ์ด์ ๊ฐ(์: userID)์ state(์: prevUserID)๋ก ์ ์งํด์ผ ํ๋ค๋ ์ ์ ์ ์ํ์ธ์.
๋งค๊ฐ๋ณ์
props: ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋งํ ๋ค์ props์ ๋๋ค.state: ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋งํ ๋ค์ state์ ๋๋ค.
๋ฐํ๊ฐ
static getDerivedStateFromProps๋ state๋ฅผ ์
๋ฐ์ดํธํ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ฑฐ๋, ์๋ฌด๊ฒ๋ ์
๋ฐ์ดํธํ์ง ์์ผ๋ฉด null์ ๋ฐํํฉ๋๋ค.
์ฃผ์์ฌํญ
-
์ด ๋ฉ์๋๋ ์์ธ์ ๊ด๊ณ์์ด ๋ชจ๋ ๋ ๋๋ง์์ ํธ์ถ๋ฉ๋๋ค. ์ด๋ ๋ถ๋ชจ๊ฐ ๋ค์ ๋ ๋๋ง์ ์ผ์ผํฌ ๋๋ง ๋ฐ๋ํ๊ณ ๋ก์ปฌ
setState์ ๊ฒฐ๊ณผ๊ฐ ์๋ ๋๋ง ๋ฐ๋ํ๋UNSAFE_componentWillReceiveProps์๋ ๋ค๋ฆ ๋๋ค. -
์ด ๋ฉ์๋์๋ ์ปดํฌ๋ํธ ์ธ์คํด์ค์ ๋ํ ์ก์ธ์ค ๊ถํ์ด ์์ต๋๋ค. ์ํ๋ ๊ฒฝ์ฐ class ์ ์ ์ธ๋ถ ์ปดํฌ๋ํธ props ๋ฐ state์ ์์ ํจ์๋ฅผ ์ถ์ถํ์ฌ
static getDerivedStateFromProps์ ๋ค๋ฅธ class ๋ฉ์๋ ์ฌ์ด์ ์ผ๋ถ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ์ฉ๋ฒ
ํด๋์ค ์ปดํฌ๋ํธ ์ ์ํ๊ธฐ
React ์ปดํฌ๋ํธ๋ฅผ class๋ก ์ ์ํ๋ ค๋ฉด ๊ธฐ๋ณธ ์ ๊ณต Component class๋ฅผ ํ์ฅํ๊ณ render ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค,
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}React๋ ํ๋ฉด์ ํ์ํ ๋ด์ฉ์ ํ์
ํด์ผ ํ ๋๋ง๋ค render ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ๋ณดํต์ JSX๋ฅผ ๋ฐํํฉ๋๋ค. render ๋ฉ์๋๋ ์์ ํจ์์ฌ์ผ ํฉ๋๋ค. JSX๋ง ๊ณ์ฐํด์ผ ํฉ๋๋ค.
ํจ์ ์ปดํฌ๋ํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก ํด๋์ค ์ปดํฌ๋ํธ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ก๋ถํฐ props๋ก ์ ๋ณด๋ฅผ ๋ฐ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค. ํ์ง๋ง props๋ฅผ ์ฝ๋ ๋ฌธ๋ฒ์ ๋ค๋ฆ
๋๋ค. ์๋ฅผ ๋ค์ด, ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ <Greeting name="Taylor" />๋ฅผ ๋ ๋๋งํ๋ ๊ฒฝ์ฐ, this.props.name๊ณผ ๊ฐ์ด this.props์์ name prop์ ์ฝ์ ์ ์์ต๋๋ค.
import { Component } from 'react'; class Greeting extends Component { render() { return <h1>Hello, {this.props.name}!</h1>; } } export default function App() { return ( <> <Greeting name="Sara" /> <Greeting name="Cahal" /> <Greeting name="Edite" /> </> ); }
ํด๋์ค ์ปดํฌ๋ํธ ๋ด๋ถ์์๋ Hooks(use๋ก ์์ํ๋ ํจ์, ์๋ฅผ ๋ค์ด useState)๊ฐ ์ง์๋์ง ์์ต๋๋ค.
ํด๋์ค ์ปดํฌ๋ํธ์ state ์ถ๊ฐํ๊ธฐ
class์ state๋ฅผ ์ถ๊ฐํ๋ ค๋ฉด state๋ผ๋ ํ๋กํผํฐ์ ๊ฐ์ฒด๋ฅผ ํ ๋นํฉ๋๋ค. state๋ฅผ ์
๋ฐ์ดํธํ๋ ค๋ฉด this.setState๋ฅผ ํธ์ถํฉ๋๋ค.
import { Component } from 'react'; export default class Counter extends Component { state = { name: 'Taylor', age: 42, }; handleNameChange = (e) => { this.setState({ name: e.target.value }); } handleAgeChange = () => { this.setState({ age: this.state.age + 1 }); }; render() { return ( <> <input value={this.state.name} onChange={this.handleNameChange} /> <button onClick={this.handleAgeChange}> Increment age </button> <p>Hello, {this.state.name}. You are {this.state.age}.</p> </> ); } }
ํด๋์ค ์ปดํฌ๋ํธ์ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋ ์ถ๊ฐํ๊ธฐ
class์์ ์ ์ํ ์ ์๋ ๋ช ๊ฐ์ง ํน๋ณํ ๋ฉ์๋๊ฐ ์์ต๋๋ค.
componentDidMount ๋ฉ์๋๋ฅผ ์ ์ํ๋ฉด ์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์ ์ถ๊ฐ (๋ง์ดํธ) ๋ ๋ React๊ฐ ์ด๋ฅผ ํธ์ถํฉ๋๋ค. ์ปดํฌ๋ํธ๊ฐ props๋ state ๋ณ๊ฒฝ์ผ๋ก ์ธํด ๋ค์ ๋ ๋๋ง๋๋ฉด React๋ componentDidUpdate๋ฅผ ํธ์ถํฉ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์์ ์ ๊ฑฐ (๋ง์ดํธ ํด์ ) ๋ ํ React๋ componentWillUnmount๋ฅผ ํธ์ถํฉ๋๋ค.
componentDidMount๋ฅผ ๊ตฌํํ๋ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก ๋ฒ๊ทธ๋ฅผ ํผํ๊ธฐ ์ํด ์ธ ๊ฐ์ง ์๋ช
์ฃผ๊ธฐ๋ฅผ ๋ชจ๋ ๊ตฌํํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด componentDidMount๊ฐ state๋ props๋ฅผ ์ฝ์๋ค๋ฉด ํด๋น ๋ณ๊ฒฝ ์ฌํญ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด componentDidUpdate๋ ๊ตฌํํด์ผ ํ๊ณ , componentDidMount๊ฐ ์ํํ๋ ์์
์ ์ ๋ฆฌํ๊ธฐ ์ํด componentWillUnmount๋ ๊ตฌํํด์ผ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ด ChatRoom ์ปดํฌ๋ํธ๋ ์ฑํ
์ฐ๊ฒฐ์ props ๋ฐ state์ ๋๊ธฐํํ์ฌ ์ ์งํฉ๋๋ค:
import { Component } from 'react'; import { createConnection } from './chat.js'; export default class ChatRoom extends Component { state = { serverUrl: 'https://localhost:1234' }; componentDidMount() { this.setupConnection(); } componentDidUpdate(prevProps, prevState) { if ( this.props.roomId !== prevProps.roomId || this.state.serverUrl !== prevState.serverUrl ) { this.destroyConnection(); this.setupConnection(); } } componentWillUnmount() { this.destroyConnection(); } setupConnection() { this.connection = createConnection( this.state.serverUrl, this.props.roomId ); this.connection.connect(); } destroyConnection() { this.connection.disconnect(); this.connection = null; } render() { return ( <> <label> Server URL:{' '} <input value={this.state.serverUrl} onChange={e => { this.setState({ serverUrl: e.target.value }); }} /> </label> <h1>Welcome to the {this.props.roomId} room!</h1> </> ); } }
Strict ๋ชจ๋๊ฐ ์ผ์ ธ ์์ ๋ ๊ฐ๋ฐํ ๋ React๋ componentDidMount๋ฅผ ํธ์ถํ๊ณ , ์ฆ์ componentWillUnmount๋ฅผ ํธ์ถํ ๋ค์, componentDidMount๋ฅผ ๋ค์ ํธ์ถํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด componentWillUnmount๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ์์ด๋ฒ๋ ธ๊ฑฐ๋ ๊ทธ ๋ก์ง์ด componentDidMount์ ๋์์ ์์ ํ โ๋ฏธ๋ฌ๋งโํ์ง ์๋์ง ์ ์ ์์ต๋๋ค.
error boundary๋ก ๋ ๋๋ง ์ค๋ฅ ํฌ์ฐฉํ๊ธฐ
๊ธฐ๋ณธ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ ๋๋ง ๋์ค ์๋ฌ๋ฅผ ๋ฐ์์ํค๋ฉด React๋ ํ๋ฉด์์ ํด๋น UI๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด UI์ ์ผ๋ถ๋ฅผ error boundary๋ก ๊ฐ์ธ๋ฉด ๋ฉ๋๋ค. error boundary๋ ์๋ฌ๊ฐ ๋ฐ์ํ ๋ถ๋ถ ๋์ ์ค๋ฅ ๋ฉ์์ง์ ๊ฐ์ fallback UI๋ฅผ ํ์ํ ์ ์๋ ํน์ ์ปดํฌ๋ํธ์ ๋๋ค.
error boundary ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๋ ค๋ฉด ์ค๋ฅ์ ๋ํ ์๋ต์ผ๋ก state๋ฅผ ์
๋ฐ์ดํธํ๊ณ ์ฌ์ฉ์์๊ฒ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ ์ ์๋ static getDerivedStateFromError๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ๋ํ ์ ํ์ ์ผ๋ก componentDidCatch๋ฅผ ๊ตฌํํ์ฌ ๋ถ์ ์๋น์ค์ ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๋ ๋ฑ์ ์ถ๊ฐ ๋ก์ง์ ์ถ๊ฐํ ์๋ ์์ต๋๋ค.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// state๋ฅผ ์
๋ฐ์ดํธํ์ฌ ๋ค์ ๋ ๋๋ง์ fallback UI๊ฐ ํ์๋๋๋ก ํฉ๋๋ค.
return { hasError: true };
}
componentDidCatch(error, info) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logErrorToMyService(error, info.componentStack);
}
render() {
if (this.state.hasError) {
// ์ฌ์ฉ์ ์ง์ fallback UI๋ฅผ ๋ ๋๋งํ ์ ์์ต๋๋ค.
return this.props.fallback;
}
return this.props.children;
}
}๊ทธ๋ฐ ๋ค์ ์ปดํฌ๋ํธ ํธ๋ฆฌ์ ์ผ๋ถ๋ฅผ ๋ํํ ์ ์์ต๋๋ค.
<ErrorBoundary fallback={<p>Something went wrong</p>}>
<Profile />
</ErrorBoundary>Profile ๋๋ ๊ทธ ํ์ ์ปดํฌ๋ํธ๊ฐ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๋ฉด ErrorBoundary๊ฐ ํด๋น ์ค๋ฅ๋ฅผ โํฌ์ฐฉโํ๊ณ ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ์ค๋ฅ ๋ฉ์์ง์ ํจ๊ป fallback UI๋ฅผ ํ์ํ ๋ค์ ํ๋ก๋์
์ค๋ฅ ๋ณด๊ณ ์๋ฅผ ์ค๋ฅ ๋ณด๊ณ ์๋น์ค์ ์ ์กํฉ๋๋ค.
๋ชจ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ณ๋์ error boundary๋ก ๋ฌถ์ ํ์๋ ์์ต๋๋ค. error boundary์ ์ธ๋ถํ๋ฅผ ๊ณ ๋ คํ ๋๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ๋ ๊ฒ์ด ์ ์ ํ ์์น๋ฅผ ๊ณ ๋ คํ์ธ์. ์๋ฅผ ๋ค์ด ๋ฉ์์ง ์ฑ์ ๊ฒฝ์ฐ error boundary๋ฅผ ๋ํ ๋ชฉ๋ก ์ฃผ์์ ์์น์ํค๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ํ ๋ชจ๋ ๊ฐ๋ณ ๋ฉ์์ง ์ฃผ์์ ์์น์ํค๋ ๊ฒ๋ ์ข์ต๋๋ค. ํ์ง๋ง ๋ชจ๋ ์๋ฐํ ์ฃผ์์ boundary๋ฅผ ์์น์ํค๋ ๊ฒ์ ์ ์ ํ์ง ์์ต๋๋ค.
๋์
class์์ ํจ์๋ก ๊ฐ๋จํ ์ปดํฌ๋ํธ ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
์ผ๋ฐ์ ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ํจ์๋ก ๋์ ์ ์ํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ด Greeting ํด๋์ค ์ปดํฌ๋ํธ๋ฅผ ํจ์๋ก ๋ณํํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
import { Component } from 'react'; class Greeting extends Component { render() { return <h1>Hello, {this.props.name}!</h1>; } } export default function App() { return ( <> <Greeting name="Sara" /> <Greeting name="Cahal" /> <Greeting name="Edite" /> </> ); }
Greeting์ด๋ผ๋ ํจ์๋ฅผ ์ ์ํฉ๋๋ค. ์ฌ๊ธฐ๋ก render ํจ์์ ๋ณธ๋ฌธ์ ์ด๋ํฉ๋๋ค.
function Greeting() {
// ... render ๋ฉ์๋์ ์ฝ๋๋ฅผ ์ฌ๊ธฐ๋ก ์ฎ๊น๋๋ค ...
}this.props.name ๋์ ๊ตฌ์กฐ ๋ถํด ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ name prop์ ์ ์ํ๊ณ ์ง์ ์ฝ์ต๋๋ค.
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}๋ค์์ ์ ์ฒด ์์ ์ ๋๋ค.
function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } export default function App() { return ( <> <Greeting name="Sara" /> <Greeting name="Cahal" /> <Greeting name="Edite" /> </> ); }
state๊ฐ ์๋ ์ปดํฌ๋ํธ๋ฅผ class์์ ํจ์๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
์ด Counter ํด๋์ค ์ปดํฌ๋ํธ๋ฅผ ํจ์๋ก ๋ณํํ๋ค๊ณ ๊ฐ์ ํด ๋ด
์๋ค.
import { Component } from 'react'; export default class Counter extends Component { state = { name: 'Taylor', age: 42, }; handleNameChange = (e) => { this.setState({ name: e.target.value }); } handleAgeChange = (e) => { this.setState({ age: this.state.age + 1 }); }; render() { return ( <> <input value={this.state.name} onChange={this.handleNameChange} /> <button onClick={this.handleAgeChange}> Increment age </button> <p>Hello, {this.state.name}. You are {this.state.age}.</p> </> ); } }
ํ์ํ state ๋ณ์๊ฐ ์๋ ํจ์๋ฅผ ์ ์ธํ๋ ๊ฒ์ผ๋ก ์์ํ์ธ์.
import { useState } from 'react';
function Counter() {
const [name, setName] = useState('Taylor');
const [age, setAge] = useState(42);
// ...๋ค์์ผ๋ก ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ณํํฉ๋๋ค.
function Counter() {
const [name, setName] = useState('Taylor');
const [age, setAge] = useState(42);
function handleNameChange(e) {
setName(e.target.value);
}
function handleAgeChange() {
setAge(age + 1);
}
// ...๋ง์ง๋ง์ผ๋ก, this์ผ๋ก ์์ํ๋ ๋ชจ๋ ๋ ํผ๋ฐ์ค๋ฅผ ์ปดํฌ๋ํธ์์ ์ ์ํ ๋ณ์ ๋ฐ ํจ์๋ก ๋ฐ๊ฟ๋๋ค. ์๋ฅผ ๋ค์ด, this.state.age๋ฅผ age๋ก ๋ฐ๊พธ๊ณ this.handleNameChange๋ฅผ handleNameChange๋ก ๋ฐ๊ฟ๋๋ค.
๋ค์์ ์์ ํ ๋ณํ๋ ์ปดํฌ๋ํธ์ ๋๋ค.
import { useState } from 'react'; export default function Counter() { const [name, setName] = useState('Taylor'); const [age, setAge] = useState(42); function handleNameChange(e) { setName(e.target.value); } function handleAgeChange() { setAge(age + 1); } return ( <> <input value={name} onChange={handleNameChange} /> <button onClick={handleAgeChange}> Increment age </button> <p>Hello, {name}. You are {age}.</p> </> ) }
์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๊ฐ ์๋ ์ปดํฌ๋ํธ๋ฅผ class์์ ํจ์๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
์๋ช
์ฃผ๊ธฐ ๋ฉ์๋๊ฐ ์๋ ChatRoom ํด๋์ค ์ปดํฌ๋ํธ๋ฅผ ํจ์๋ก ๋ณํํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
import { Component } from 'react'; import { createConnection } from './chat.js'; export default class ChatRoom extends Component { state = { serverUrl: 'https://localhost:1234' }; componentDidMount() { this.setupConnection(); } componentDidUpdate(prevProps, prevState) { if ( this.props.roomId !== prevProps.roomId || this.state.serverUrl !== prevState.serverUrl ) { this.destroyConnection(); this.setupConnection(); } } componentWillUnmount() { this.destroyConnection(); } setupConnection() { this.connection = createConnection( this.state.serverUrl, this.props.roomId ); this.connection.connect(); } destroyConnection() { this.connection.disconnect(); this.connection = null; } render() { return ( <> <label> Server URL:{' '} <input value={this.state.serverUrl} onChange={e => { this.setState({ serverUrl: e.target.value }); }} /> </label> <h1>Welcome to the {this.props.roomId} room!</h1> </> ); } }
๋จผ์ componentWillUnmount๊ฐ componentDidMount์ ๋ฐ๋ ๋์์ ํ๋์ง ํ์ธํฉ๋๋ค. ์์ ์์์์๋ componentDidMount๊ฐ ์ค์ ํ ์ฐ๊ฒฐ์ ๋์ต๋๋ค. ์ด๋ฌํ ๋ก์ง์ด ๋๋ฝ๋ ๊ฒฝ์ฐ ๋จผ์ ์ถ๊ฐํ์ธ์.
๋ค์์ผ๋ก, componentDidUpdate ๋ฉ์๋๊ฐ componentDidMount์์ ์ฌ์ฉ ์ค์ธ props ๋ฐ state์ ๋ณ๊ฒฝ ์ฌํญ์ ์ฒ๋ฆฌํ๋์ง ํ์ธํฉ๋๋ค. ์์ ์์์์ componentDidMount๋ this.state.serverUrl๊ณผ this.props.roomId๋ฅผ ์ฝ๋ setupConnection์ ํธ์ถํฉ๋๋ค. ์ด ๋๋ฌธ์ componentDidUpdate๋ this.state.serverUrl๊ณผ this.props.roomId๊ฐ ๋ณ๊ฒฝ๋์๋์ง ํ์ธํ๊ณ , ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ ์ฐ๊ฒฐ์ ์ฌ์ค์ ํฉ๋๋ค. componentDidUpdate ๋ก์ง์ด ๋๋ฝ๋์๊ฑฐ๋ ๋ชจ๋ ๊ด๋ จ props ๋ฐ state์ ๋ณ๊ฒฝ ์ฌํญ์ ์ฒ๋ฆฌํ์ง ์๋ ๊ฒฝ์ฐ ๋จผ์ ํด๋น ๋ก์ง์ ์์ ํ์ธ์.
์์ ์์์์, ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋ ๋ด๋ถ์ ๋ก์ง์ ์ปดํฌ๋ํธ๋ฅผ React ์ธ๋ถ์ ์์คํ (์ฑํ ์๋ฒ)์ ์ฐ๊ฒฐํฉ๋๋ค. ์ปดํฌ๋ํธ๋ฅผ ์ธ๋ถ ์์คํ ์ ์ฐ๊ฒฐํ๋ ค๋ฉด ์ด ๋ก์ง์ ํ๋์ Effect๋ก ์ค๋ช ํ์ธ์.
import { useState, useEffect } from 'react';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}์ด useEffect ํธ์ถ์ ์์ ์๋ช
์ฃผ๊ธฐ ๋ฉ์๋์ ๋ก์ง๊ณผ ๋์ผํฉ๋๋ค. ์๋ช
์ฃผ๊ธฐ ๋ฉ์๋๊ฐ ์๋ก ๊ด๋ จ์ด ์๋ ์ฌ๋ฌ ๊ฐ์ง ์์
์ ์ํํ๋ ๊ฒฝ์ฐ, ์ด๋ฅผ ์ฌ๋ฌ ๊ฐ์ ๋
๋ฆฝ์ ์ธ Effect๋ก ๋ถํ ํ์ธ์. ๋ค์์ ์์ ํ ์์ ์
๋๋ค.
import { useState, useEffect } from 'react'; import { createConnection } from './chat.js'; export default function ChatRoom({ roomId }) { const [serverUrl, setServerUrl] = useState('https://localhost:1234'); useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => { connection.disconnect(); }; }, [roomId, serverUrl]); return ( <> <label> Server URL:{' '} <input value={serverUrl} onChange={e => setServerUrl(e.target.value)} /> </label> <h1>Welcome to the {roomId} room!</h1> </> ); }
context๊ฐ ์๋ ์ปดํฌ๋ํธ๋ฅผ class์์ ํจ์๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ
์ด ์์ ์์ Panel ๋ฐ Button ํด๋์ค ์ปดํฌ๋ํธ๋ this.context์์ context๋ฅผ ์ฝ์ต๋๋ค:
import { createContext, Component } from 'react'; const ThemeContext = createContext(null); class Panel extends Component { static contextType = ThemeContext; render() { const theme = this.context; const className = 'panel-' + theme; return ( <section className={className}> <h1>{this.props.title}</h1> {this.props.children} </section> ); } } class Button extends Component { static contextType = ThemeContext; render() { const theme = this.context; const className = 'button-' + theme; return ( <button className={className}> {this.props.children} </button> ); } } function Form() { return ( <Panel title="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> </Panel> ); } export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> ) }
ํจ์ ์ปดํฌ๋ํธ๋ก ๋ณํํ ๋๋ this.context๋ฅผ useContext ํธ์ถ๋ก ๋ฐ๊ฟ์ฃผ์ธ์.
import { createContext, useContext } from 'react'; const ThemeContext = createContext(null); function Panel({ title, children }) { const theme = useContext(ThemeContext); const className = 'panel-' + theme; return ( <section className={className}> <h1>{title}</h1> {children} </section> ) } function Button({ children }) { const theme = useContext(ThemeContext); const className = 'button-' + theme; return ( <button className={className}> {children} </button> ); } function Form() { return ( <Panel title="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> </Panel> ); } export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> ) }