๐ก ํจ์ํ ์ปดํฌ๋ํธ๊ฐ ๋์ ๋ ์ง ์๊ฐ์ด ๊ฝค ํ๋ฌ์ ์ค๋ฌด์์๋ ํด๋์คํ๋ณด๋ค ํจ์ํ์ ๋ ๋ง์ด ์ฐ๊ณ ์๋ค๊ณ ํฉ๋๋ค.
React ๊ณต์๋ฌธ์์๋ ํจ์ํ์ ์ธ ๊ฒ์ ๊ถ๊ณ ํ๊ณ ์์ต๋๋ค. ํ์ง๋ง ํ์ฌ์ ์ค๋๋ heritage๋ก ํด๋์คํ ์ปดํฌ๋ํธ๋ฅผ ๋ง์ฃผ์น ์ ์๋ ์ํฉ๋ ์์ ์ ์์ผ๋ ์ด๋ฅผ ๋๋นํ์ฌ ์ฌ์ (?) ์ง์์ผ๋ก์ ์งง๊ฒ ์์๋ณด๋ ์๊ฐ์ ๊ฐ์ก์ต๋๋ค.
1. LifeCycle

๋ฆฌ์กํธ์ ๋ผ์ดํ ์ฌ์ดํด์ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง์ ์ค๋นํ๋ ์๊ฐ๋ถํฐ ์ฌ๋ผ์ง ๋๊น์ง์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๋ปํฉ๋๋ค.
๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ [Mount] -> [Update] -> [Unmount] ์ ๊ณผ์ ์ ๊ฑฐ์นฉ๋๋ค. mount๋ ์์ฑ๋ ๋, update๋ ์ ๋ฐ์ดํธ๋ ๋, unmount๋ ์ ๊ฑฐ๋ ๋๋ฅผ ๋ปํฉ๋๋ค.
๋ผ์ดํ ์ฌ์ดํด ๋ฉ์๋์ ์ข ๋ฅ๋ ์ด 10๊ฐ์ง ์ ๋๋ค.
will ์ ๋์ฌ๊ฐ ๋ถ์ ๋ฉ์๋๋ ์ด๋ค ์์ ์ ์๋ํ๊ธฐ ์ ์ ์คํ๋ฉ๋๋ค.
Did ์ ๋์ฌ๊ฐ ๋ถ์ ๋ฉ์๋๋ ์ด๋ค ์์ ์ ์๋ํ ํ์ ์คํ๋ฉ๋๋ค.
๋ง์ดํธ(Mount)
DOM ์ด ์์ฑ๋๊ณ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ํ๋๋ ๊ฒ์ Mount ๋ผ๊ณ ํฉ๋๋ค.
๋ง์ดํธ ์ ํธ์ถ๋๋ ๋ฉ์๋
- constructor : ์ปดํฌ๋ํธ๋ฅผ ์๋ก ๋ง๋ค ๋๋ง๋ค ํธ์ถ๋๋ ํด๋์ค ์์ฑ์ ๋ฉ์๋
- getDerivedStateFromProps: props์ ์๋ ๊ฐ์ state ์ ๋ฃ์ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋
- render : ์ค๋นํ UI๋ฅผ ๋ ๋๋งํ๋ ๋ฉ์๋
- componentDidMount : ์ปดํฌ๋ํธ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ํ๋ ํ ํธ์ถํ๋ ๋ฉ์๋
componentWillMount (deprecated): ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋ ๋ฉ์๋์ ๋๋ค. ์๋ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋๊ธฐ ์ง์ ์ ํธ์ถ๋์์ต๋๋ค. ๋ฉ์๋์ ๊ฐ์์์ ์ ์ธํ์์ต๋๋ค.
์ ๋ฐ์ดํธ(Update)
์ปดํฌ๋ํธ๋ ๋ค์ 4๊ฐ์ง ๊ฒฝ์ฐ์ ์ ๋ฐ์ดํธํฉ๋๋ค.
- props๊ฐ ๋ฐ๋ ๋(์๋ก์ด props๊ฐ ๋ค์ด์์ ๋, ๊ธฐ์กด props๊ฐ ๋ฐ๋ ๋)
- state๊ฐ ๋ฐ๋ ๋
- ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋
- (ํด๋์ค ์ปดํฌ๋ํธ) this.forceUpdate๋ก ๊ฐ์ ๋ก ๋ ๋๋ง ํธ๋ฆฌ๊ฑฐ ํ ๋
์ ๋ฐ์ดํธ์ ํธ์ถ๋๋ ๋ฉ์๋
- getDerivedStateFromProps : ์์ Mount์์๋ ํธ์ถ๋๊ณ , props์ ๋ณํ์ ๋ฐ๋ผ state ๊ฐ์๋ ๋ณํ๋ฅผ ์ฃผ๊ณ ์ถ์ ๋ ์ฌ์ฉ
- shouldComponentUpdate : ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง์ ํด์ผ ํ ์ง ๋ง์์ผ ํ ์ง๋ฅผ ๊ฒฐ์ , true๋ฅผ ๋ฐํํ๋ฉด ๋ค์ ๋ผ์ดํ ์ฌ์ดํด ๋ฉ์๋๋ฅผ ๊ณ์ ์คํ. false๋ฅผ ๋ฐํํ๋ฉด ์์ ์ ์ค์ง(๋ฆฌ๋ ๋๋งX) ํฉ๋๋ค.
- render : ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ํฉ๋๋ค.
- getSnapShotBeforeUpdate : ์ปดํฌ๋ํธ ๋ณํ๋ฅผ DOM์ ๋ฐ์ํ๊ธฐ ๋ฐ๋ก ์ง์ ์ ํธ์ถ
- componentDidUpdate : ์ปดํฌ๋ํธ์ ์ ๋ฐ์ดํธ ์์ ์ด ๋ค ๋๋ ํ์ ํธ์ถ
์ธ๋ง์ดํธ(Unmount)
Mount์ ๋ฐ๋ ๊ณผ์ ์ ๋๋ค. ์ปดํฌ๋ํธ๋ฅผ DOM์์ ์ ๊ฑฐํ๋ ๊ฒ์ Unmount ๋ผ๊ณ ํฉ๋๋ค.
์ธ๋ง์ดํธ ์ ํธ์ถ๋๋ ๋ฉ์๋
- componentWillUnmount : ์ปดํฌ๋ํธ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์์์ ์ฌ๋ผ์ง๊ธฐ ์ ์ ํธ์ถ
์ ๋ผ์ดํ ์ฌ์ดํด๊ณผ ๊ด๋ จํด์ ํด๋์คํ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ ์ ์๋ ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋ ๋ช ๊ฐ์ง๋ฅผ ํจ์ํ ์ปดํฌ๋ํธ์ ๋น๊ตํ๋ฉฐ ์ ๋ฆฌํด๋ณด์์ต๋๋ค.
1. constructor(props) - Mount
[ํด๋์คํ ์ปดํฌ๋ํธ]
component ์์ฑ์ ๋ฉ์๋์ ๋๋ค. ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋ ์ ์ผ ๋จผ์ ์คํ๋ฉ๋๋ค. ํจ์ํ ์ปดํฌ๋ํธ์ useState ํ ์ฒ๋ผ ์ด๊ธฐ state๋ฅผ ์ ํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๊ผญ State๋ฅผ constructor ํจ์ ์์์ ์ด๊ธฐํํ ํ์๋ ์์ต๋๋ค.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { number: 0 };
}
[ํจ์ํ ์ปดํฌ๋ํธ]
const Example = () => {
const [count,setCount] = useState(0);
}
2. render() - Mount
[ํด๋์คํ ์ปดํฌ๋ํธ]
์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ ๋ฉ์๋์ ๋๋ค.
// Class
class Example extends React.Component {
render() {
return <div>Component</div>
}
}
- this.props์ this.state ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
- ๋ฆฌ์กํธ ์์๋ฅผ ๋ฐํํฉ๋๋ค.
- render ํจ์ ์์์๋ ์ด๋ฒคํธ ์ค์ ์ด ์๋ ๊ณณ์์ setState๋ฅผ ์ฌ์ฉํ์ง ์๊ณ , ๋ธ๋ผ์ฐ์ ์ DOM ์ ์ ๊ทผํด์๋ ์ ๋ฉ๋๋ค.
- DOM ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ State ๋ณํ๋ฅผ ์ค ๋๋ ์ดํ์ ์คํ๋๋ componentDidMount ์์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
[ํจ์ํ ์ปดํฌ๋ํธ]
ํจ์ํ ์ปดํฌ๋ํธ์์๋ render๋ฅผ ์ฐ์ง ์๊ณ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋ง ํ ์ ์์ต๋๋ค.
const example = () => {
return <div>Component</div>
}
3. shouldComponentUpdate(nextProps, nextState) - - - ๋ ๋๋ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ !
props ๋๋ state๋ฅผ ๋ณ๊ฒฝํ์ ๋ ๋ฆฌ๋ ๋๋ง์ ์์ํ ์ง ์ฌ๋ถ๋ฅผ ์ง์ ํฉ๋๋ค. true ๋๋ false๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค.
- ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋, ๋ฐ๋ก ๋ง๋ค์ง ์์ ๊ฒฝ์ฐ default ๋ก true ๋ฅผ ๋ฐํ(true ๋ฐํ๋ผ์ ๊ณ์ ๋ ๋๋ง ํ๊ฒ ๋จ)ํฉ๋๋ค.
- false๋ฅผ ๋ฐํํ๋ฉด, ์ ๋ฐ์ดํธ ๊ณผ์ [๋ ๋๋ง]์ ์ค์งํฉ๋๋ค.
- ์ด ๋ฉ์๋ ์์์ props์ state๋ this.props, this.state๋ก ์ ๊ทผํ๊ณ , ์๋ก ์ค์ ๋ props, state๋ nextProps, nextState๋ก ์ ๊ทผํฉ๋๋ค.
- ํ๋ก์ ํธ ์ฑ๋ฅ์ ์ต์ ํํ ๋, ๋ฆฌ๋ ๋๋ง์ ๋ฐฉ์งํ ๋๋ false๋ฅผ ๋ฐํํ๋๋ฐ, ์ด๋ ์ปดํฌ๋ํธ ๋ ๋๋ง์ ์ต์ ํ ํ ๋ ์ค์ํฉ๋๋ค.
4. getSnapshotBeforeUpdate(prevProps, prevState)
render ์์ ๋ง๋ค์ด์ง ๊ฒฐ๊ณผ๋ฌผ์ด ๋ธ๋ผ์ฐ์ ์ ์ค์ ๋ก ๋ฐ์๋๊ธฐ ์ง์ ์ ํธ์ถ๋ฉ๋๋ค.
- getSnapshotBeforeUpdate์ ๋ฐํ ๊ฐ์ componentDidUpdate ์์ ์ธ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์ธ snapshot ๊ฐ์ผ๋ก ์ ๋ฌ๋ฐ์ต๋๋ค.
- ์ฃผ๋ก ์ ๋ฐ์ดํธ ํ๊ธฐ ์ง์ ์ ๊ฐ์ ์ฐธ๊ณ ํ ์ผ์ด ์์ ๋ ํ์ฉํฉ๋๋ค. (ex: ์คํฌ๋กค๋ฐ ์์น ์ ์ง)
5. componentDidMount, componentDidUpdate, componentWillUnmount, getDerivedStateFromProps
[ํด๋์คํ ์ปดํฌ๋ํธ]
5-1 componentDidMount() -- (mount)
์ปดํฌ๋ํธ์ ์ฒซ ๋ ๋๋ง์ ๋ง์น๊ณ ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋์ ๋๋ค. ์ด ๋ฉ์๋๊ฐ ํธ์ถ๋ ๋๋ ์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์ ๋ํ๋ ์๋ ์ํ์ ๋๋ค.
- ๋ค๋ฅธ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ ํ๋ ์์ํฌ์ ํจ์๋ฅผ ํธ์ถํ๊ฒ ๋ฉ๋๋ค.
- ์ด๋ฒคํธ ๋ฑ๋ก, setTimeout, setInterval, ๋คํธ์ํฌ ์์ฒญ ๊ฐ์ ๋น๋๊ธฐ ์์ ์ ์ฒ๋ฆฌํฉ๋๋ค.
// Class
class Example extends React.Component {
componentDidMount() {
...
}
}
[ํจ์ํ ์ปดํฌ๋ํธ]
ํจ์ํ ์ปดํฌ๋ํธ์์๋ useEffect ํ ์ด ์์กด์ฑ ๋ฐฐ์ด๊ฐ์ผ๋ก ๋น ๋ฐฐ์ด์ ๊ฐ์ง๋ฉด useEffect ๋ด๋ถ์ ์ฝ๋ฐฑํจ์๊ฐ componentDidMount ํ์ ๋๋ง ์คํํ๋๋ก ์ญํ ์ ํด์ค๋๋ค.
// Function
function Example(){
useEffect(() => {
...
}, [])
}
5-2. getDerivedStateFromProps(nextProps, preState)
- ๋ฆฌ์กํธ v 16.3 ์ดํ์ ์๋ก ์ถ๊ฐ๋์์ต๋๋ค.
- props๋ก ๋ฐ์์จ ๊ฐ์ state์ ๋๊ธฐํ์ํค๋ ์ฉ๋๋ก ์ฌ์ฉํฉ๋๋ค. ์ปดํฌ๋ํธ๊ฐ Mount, Update๋ ๋ ํธ์ถ๋ฉ๋๋ค.
[ํด๋์คํ]
static getDerivedStateFromProps(nextProps, prevState) {
// ์กฐ๊ฑด์ ๋ฐ๋ผ ํน์ ๊ฐ ๋๊ธฐํ
if(nextProps.value !== prevState.value) {
return { value: nextProps.value };
}
return null; // state ๋ณ๊ฒฝํ ํ์ ์์ ๊ฒฝ์ฐ null ๋ฐํ
}
[ํจ์ํ]
ํจ์ํ์ ๋ฐ๋ก ๋ฐ์์ componentDidUpdate์ ํจ์ํ๊ณผ ํจ๊ป ๋ค๋ฃน๋๋ค.
5-2 componentDidUpdate(prevProps, prevState, snapshot) -- (update)
๋ฆฌ๋ ๋๋ง์ ์๋ฃํ ํ ๋ณํ๊ฐ ๋ชจ๋ ๋ฐ์๋ ๋ค์ ์คํ๋ฉ๋๋ค. ์ ๋ฐ์ดํธ๊ฐ ๋๋ ์งํ์ด๋ฏ๋ก DOM ๊ด๋ จ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์ต๋๋ค. ๋งค๊ฐ๋ณ์๋ก prevProps์ prevState๊ฐ ์์ต๋๋ค.
- prevprops ๋๋ prevState๋ฅผ ํตํด ์ปดํฌ๋ํธ๊ฐ ์ด์ ์ ๊ฐ์ก๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
- getSnapshotBeforeUpdate ์์ ๋ฐํํ ๊ฐ์ด ์์ผ๋ฉด ์ฌ๊ธฐ์ snapshot ๊ฐ์ ์ ๋ฌ๋ฐ์ ์ ์์ต๋๋ค.
// Class
class Example extends React.Component {
componentDidUpdate(prevProps, prevState, snapshot) {
...
}
}
[ํจ์ํ]
- ์์กด์ฑ ๋ฐฐ์ด๊ฐ์ ์์กดํ ๊ฐ๋ค์ ๋ฃ์ด์ฃผ๋ฉด ๋ง์ดํธ(์ต์ด ๋ ๋๋ง) ์งํ์ ์ฝ๋ฐฑํจ์(effect ํจ์) ์คํ ๋ฐ ํด๋น ์์กด์ฑ ๋ฐฐ์ด๊ฐ์ ๋ณํ๋ฅผ ๊ฐ์งํ์ฌ effect ํจ์๋ฅผ ์คํํฉ๋๋ค.
- ์ด์ ์ ๋ฐํ๋ clean-up ํจ์๊ฐ ์๋ค๋ฉด, ์ด clean-up์ ๋จผ์ ํธ์ถํ ํ effect ํจ์๋ฅผ ์คํํฉ๋๋ค.(์ด๋ ๊ฒฐ๊ตญ ๋ค์ clean-up ํจ์๋ฅผ ๋ฐํํ์ฌ ๋ค์ clean-up ํจ์๊ฐ ๋จ๊ฒ ๋จ.)
/* Function */
function Component () {
useEffect(() => {
...
}, [state1, state2])
}
function Component2 () {
useEffect(() => {
...
return () => {...}
}, [state1, state2])
}
5-3 componentWillUnmount() -- (unmount) ( ์ฃผ์! componentDidUnmount() ๋ผ๋ ๊ฒ์ ์์ต๋๋ค. )
์ปดํฌ๋ํธ๋ฅผ DOM์์ ์ ๊ฑฐํ ๋ ์คํ๋ฉ๋๋ค. componentDidMount ์์ ๋ฑ๋กํ ์ด๋ฒคํธ, ํ์ด๋จธ, ์ง์ ์์ฑํ DOM์ด ์๋ค๋ฉด ์ฌ๊ธฐ์ ์ ๊ฑฐ ์์ ์ ํด์ผ ํฉ๋๋ค. ํจ์ํ ์ปดํฌ๋ํธ useEffect ํ ์ cleanup ํจ์์ ๊ฐ์ ์ญํ ์ ์ํํ ์ ์์ต๋๋ค.
[ํด๋์คํ]
// Class
class Example extends React.Component {
componentWillUnmount() {
...
}
}
[ํจ์ํ]
componentWillUnmount์ ์ญํ ์ clean-up ํจ์๊ฐ ์คํํ๊ฒ ๋ฉ๋๋ค. clean-up ํจ์๋ effect(์ฝ๋ฐฑ ํจ์)์ ๋ฐํ๋๋ ํจ์๋ฅผ ๋ปํฉ๋๋ค. unmount ์ง์ ์ ํธ์ถ๋ฉ๋๋ค.
/* Function */
function Component () {
useEffect(() => {
...
return () => { ... }
}, [])
}
2. ์์ธ์ฒ๋ฆฌ ์๋ช ์ฃผ๊ธฐ
์๋ช ์ฃผ๊ธฐ ๋ฉ์๋์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด getDerivedStateFromError ๋๋ componentDidCatch ๋ฉ์๋๋ฅผ ๊ตฌํํ ๊ฐ์ฅ ๊ฐ๊น์ด ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ฅผ ์ฐพ๊ฒ ๋ฉ๋๋ค. ๋ฆฌ์กํธ์ ํ ์ ์ปดํฌ๋ํธ์ ์๋ช ์ฃผ๊ธฐ ์ค getDerivedStateFromError์ componentDidCatch ๋ฉ์๋๋ฅผ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ํจ์ํ ์ปดํฌ๋ํธ๋ก๋ ์๋ฌ ๊ฒฝ๊ณ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- getDerivedStateFromError(error)
- componentDidCatch(error, info)
6. getDerivedStateFromError(error)
- ํ์์ ์ปดํฌ๋ํธ์์ ์ ๋ฌ๋ฐ์ ์ค๋ฅ๋ฅผ ํด๋์ค ์ปดํฌ๋ํธ ๋ด๋ถ์ ์ค๋ฅ state์ ์ ์ฅํ์ฌ ์ต์ ํํ๊ณ , ์ ๋ฐ์ดํธ๋ ์๋ฌ ์ํ๋ฅผ ํ๋ฉด์ ๋ํ๋ด๋ ์ฉ๋๋ก ์ฐ์ ๋๋ค.
- ๋ฐ๋์ ๊ฐฑ์ ๋ state๋ฅผ ๋ฐํํ์ฌ fallback UI๋ฅผ ํ์ํ ์ ์๋๋ก ํด์ผ ํฉ๋๋ค.
static getDerivedStateFromError(error: Error): TerrorBoundaryState {
// ์ค๋ฅ ์ํ ์
๋ฐ์ดํธ
return {
hasError: true,
error,
};
}
์ด ๋ ์ฃผ์ํ ์ ์ด ์์ต๋๋ค.
๐จ์ฌ์ด๋ ์ดํํธ๊ฐ ๋ฐ์ํ๋ ์์ ์ ํด์๋ ์ ๋๋ค.
getDerivedStateFromError ๋ฉ์๋๋ ์ปดํฌ๋ํธ์ render ๋จ๊ณ์์ ํธ์ถ๋ฉ๋๋ค. ์ฆ, render() ๋ฉ์๋๊ฐ ์คํ๋๊ธฐ ์ ์ ํธ์ถ๋๊ธฐ ๋๋ฌธ์ Virtual DOM(VDOM)์ ์ํฅ์ ๋ผ์น ์ ์๋ ์ฌ์ด๋ ์ดํํธ๊ฐ ๋ฐ์ํ๋ ์์ ์ ํด์๋ ์ ๋ฉ๋๋ค. ์ด ๋๋ ๋์ componentDidCatch ๋ฉ์๋๋ฅผ ์ด์ฉํด์ผ ํฉ๋๋ค.

โgetDerivedStateFromError์์ ์๋ฌ์ ๋ณด๋ฅผ ์๋ฒ๋ก ์ ์กํ์ง ์๋์ด์ (์ฐธ๊ณ ๋งํฌ)
๋ฆฌ์กํธ์์ ๋ฐ์ดํฐ๋ณ๊ฒฝ์ ์ํ ํ๋ฉด์ ๋ฐ์ดํธ๋ ๋ ๋๋จ๊ณ์ ์ปค๋ฐ๋จ๊ฒ๋ฅผ ๊ฑฐ์นฉ๋๋ค. ๋น๋๊ธฐ ๋ ๋๋ง(๋์ค์ react์ ์ถ๊ฐ๋ ์ ์๋? ํน์ ์ถ๊ฐ๋)์์๋ ๋ ๋๋จ๊ณ์์ ์คํ์ ๋ฉ์ท๋ค๊ฐ ๋ค์ ์คํํ๋ ๊ณผ์ ์์ ๊ฐ์ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ฅผ ์ฌ๋ฌ๋ฒ ํธ์ถํ ์๋ ์์ต๋๋ค..๋ค์ ๋งํด getSnapshotBeforeUpdate, componentDidMount, componentDidUpdate, componentDidCatch๋ฅผ ์ ์ธํ๊ณ ๋ ์ฌ๋ฌ๋ฒ ํธ์ถ ๋ ์๋ ์๋ค๋ ๊ฒ์ธ๋ฐ, ๋ฐ๋ผ์ getDerivedStateFromError์์ ์๋ฒ๋ก ์๋ฌ ์ ์ก์ ์ฌ๋ฌ ๋ฒ ํ์ง ์๋๋ก componentDidCatch์์ ์๋ฌ์ ์ก์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
7. componentDidCatch(error, info)
์๋ฌ ์ ๋ณด๋ฅผ ์๋ฒ๋ก ์ ์กํ๋ ์ฉ๋๋ก ์ฌ์ฉ๋ฉ๋๋ค.
- ํ์์ ์ปดํฌ๋ํธ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ํธ์ถ๋๊ณ , ํด๋น ์ค๋ฅ์ ์ด๋ค ์ปดํฌ๋ํธ๊ฐ ์ค๋ฅ๋ฅผ ๋ฐ์์์ผฐ๋์ง์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ง componentStack ํค๋ฅผ ํฌํจํ ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค.
- ๋ค๋ง, ํ๊ณ์ ์ด ์๋๋ฐ, ์ด ๋ฉ์๋๋ ์ปดํฌ๋ํธ ์์ ์๊ฒ ๋ฐ์ํ๋ ์๋ฌ๋ ์ก์๋ผ ์ ์๊ณ , ์์ ์ this.props.children ์ผ๋ก ์ ๋ฌ๋๋ ์ปดํฌ๋ํธ์์ ๋ฐ์ํ๋ ์๋ฌ๋ง ์ก์๋ผ ์ ์์ต๋๋ค.
- getDerivedStateFromError ๋ฉ์๋์ ๋ฌ๋ฆฌ render ๋จ๊ณ ์ดํ์ commit ๋จ๊ณ์์ ํธ์ถ๋๊ธฐ ๋๋ฌธ์ ์ฌ์ด๋ ์ดํํธ๊ฐ ๋ฐ์ํ๋ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
console.log({ error, errorInfo });
}
8. custom error boundary ๋ง๋ค๊ธฐ
์์์ ์๊ธฐํ๋ฏ์ด ๋ฆฌ์กํธ์์๋ errorboundary๋ฅผ ํจ์ํ ์ปดํฌ๋ํธ๋ก๋ ๋ง๋ค ์ ์์ด์ ์ง์ ํด๋์ค ์ปดํฌ๋ํธ๋ก ๋ง๋ค์ด์ ์ฌ์ฉํด์ผ ํ๋๋ฐ ์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์์ต๋๋ค. ํด๋น error boundary๋ ํ์ `suspense`์ ํจ๊ป ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
import React, { Component, ComponentType, createElement } from 'react';
/**
* ErrorBoundary ๋ด๋ถ State.
*
* `hasError` (error๊ฐ ์๋์ง ์ฌ๋ถ)์ error(`Error`๊ฐ์ฒด)๋ฅผ ๊ฐ๊ฒ ๋๋ค.
*/
type TerrorBoundaryState = {
hasError: boolean;
error: Error | null;
};
/**
* fallback property์ ์ฌ ์ปดํฌ๋ํธ๊ฐ ๋ฐ์ prop
*/
type TfallbackProps = {
/**
* ์๋ฌ ๊ฐ์ฒด ๋ด๊ธด prop
*/
error: Error | null;
/**
* `QueryErrorResetBoundary`์์ ๋๊ฒจ์ค `reset` ํจ์๋ฅผ `onReset ํ๋กํผํฐ`๋ก ๋ฐ๊ฒ ๋์ด์์. ๊ทธ onReset์ ์คํํ๊ณ ์๋ฌ ์ํ๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ด๊ธฐํ ํ๋ ํจ์ prop
*/
resetErrorBoundary: () => void; // resetErrorBoundary ํจ์๋ฅผ ์ฌ์ฉํ๋ ์ชฝ์์ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก props๋ก ์ ๋ฌ
};
/**
* ErrorBoundary๊ฐ ๋ฐ๊ฒ ๋ Props
*/
export type TerrorBoundaryProps = {
/**
* @description fallback ์ฉ๋์ ์ปดํฌ๋ํธ๋ Error ์ ๋ณด๋ฅผ props๋ก ๋ฐ์ ์ ์๋ ์ปดํฌ๋ํธ์ฌ์ผ ํ๋ค.
*/
fallback: ComponentType<TfallbackProps>;
onReset: () => void;
children: React.ReactNode;
};
class ErrorBoundary extends Component<TerrorBoundaryProps, TerrorBoundaryState> {
constructor(props: TerrorBoundaryProps) {
super(props); // Constructors for derived classes must contain a 'super' call.ts(2377) => ๊ทธ๋ ๋ค๊ณ ํ๋ค.
this.state = {
hasError: false, // ์ค๋ฅ๊ฐ ๋ฐ์ํ๋์ง ์ฌ๋ถ๋ฅผ state ์ํ๋ก ์ ์ฅ
error: null, // ๋ฐ์ํ ์ค๋ฅ์ ์ ๋ณด๋ฅผ state ์ํ๋ก ์ ์ฅ
};
this.resetErrorBoundary = this.resetErrorBoundary.bind(this); // โ this ๋ฐ์ธ๋ฉ ์ฒ๋ฆฌ. ์ ๊ตณ์ด ๋ฐ์ธ๋ฉ์ ํ์๊น? `์ฌ๊ธฐ ๊ณต๋ถ ํ์ํจ`
}
/**
* derived ์ ๋๋, ํ์๋
* `getDerivedStateFromError` ๋ฉ์๋๋ ํ์ ์ปดํฌ๋ํธ์์ ์ค๋ฅ์ ์ ๋ณด๋ฅผ return์ ํตํด์ State์ ์ ์ฅํ๋ ์ญํ ์ ํฉ๋๋ค.error ํ๋ผ๋ฏธํฐ๋ ๋ฐ์ํ ์ค๋ฅ์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ต๋๋ค.
*/
static getDerivedStateFromError(error: Error): TerrorBoundaryState {
// ์ค๋ฅ ์ํ ์
๋ฐ์ดํธ
return {
hasError: true,
error,
};
}
/**
* `QueryErrorResetBoundary`์์ ๋๊ฒจ์ค `reset` ํจ์๋ฅผ `onReset ํ๋กํผํฐ`๋ก ๋ฐ๊ฒ ๋์ด์์. ๊ทธ onReset์ ์คํํ๊ณ ์๋ฌ ์ํ๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ด๊ธฐํ ํ๋ ํจ์
*/
resetErrorBoundary(): void {
this.props.onReset();
// ์๋ฌ ์ํ๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ด๊ธฐํํฉ๋๋ค.
this.setState({
hasError: false,
error: null,
});
}
/**
* TIL: componentDidCatch ๋ฉ์๋๋ ์ค๋ฅ ์ ๋ณด์ ์์ธ ์ ๋ณด๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ์ป์ ์ ์์ต๋๋ค. ์ฃผ๋ก ์ค๋ฅ๋ฅผ ๋ก๊น
ํด์ผ ํ ๋ ํด๋น ๋ฉ์๋์ ์ ๊ทผํด์ ๋ก๊น
ํ ์ ์์ต๋๋ค.
* * error๋ ์ด๋ค ์๋ฌ๊ฐ ๋ฐ์ํ๋์ง, errorInfo๋ ์ด๋์ ์๋ ์ฝ๋์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋์ง์ ๋ํ ์ ๋ณด์
๋๋ค.
*/
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
console.log({ error, errorInfo });
}
render(): React.ReactNode {
const { state, props, resetErrorBoundary } = this;
const { hasError, error } = state;
const { fallback, children } = props;
const fallbackProps: TfallbackProps = {
error,
resetErrorBoundary,
};
/**
* fallback ์ปดํฌ๋ํธ ์ธก์์ ์ค๋ฅ ์ ๋ณด๋ฅผ props๋ก ๋ฐ์ ์ ์๋๋ก ์ค์
*/
const fallbackComponent = createElement(fallback, fallbackProps);
/**
* `hasError` state๋ฅผ ํตํด ์ค๋ฅ ๋ฐ์ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ์ฌ, ์ค๋ฅ๊ฐ ๋ฐ์ํ์๋ ์กฐ๊ฑด๋ถ ๋ ๋๋ง ์ฒ๋ฆฌ๋ฅผ ํด์ค๋๋ค.
*/
return hasError ? fallbackComponent : children;
}
}
export default ErrorBoundary;
ํจ์ํ ์ปดํฌ๋ํธ์ ์ฌ๋ฌ hook์ ๋ฐ๋ก ๊ธ์ ์ ๋ฆฌํด ๋์์ต๋๋ค.
๐๋ฆฌ์กํธ ํจ์ํ ์ปดํฌ๋ํธ ์ฌ๋ฌ hooks
ํจ์ํ ์ปดํฌ๋ํธ๋ก ๋ง์ด ๋์ด์จ ์ด์ ์ ๋ฆฌ
1. `this`๋ก ํ์ฌ ์์ฑ์์ ์ ๊ทผํ๊ธฐ ๋๋ฌธ์ sideEffect๊ฐ ๋ฐ์ํ ์ ์๋ ํด๋์คํ ์ปดํฌ๋ํธ. `ํด๋ก์ `๋ก ์ด์ state์ ๋ ์์ปฌ ์ค์ฝํ๋ก ์ ๊ทผํ ์ ์๋ ํจ์ํ ์ปดํฌ๋ํธ์ ๋นํด์ ํด๋์คํ ์ปดํฌ๋ํธ๋ ์ง๊ธ ๋น์ฅ์ `this`๊ฐ ๊ฐ๋ฆฌํค๊ฒ ๋๋ ์์ฑ์๋ฅผ ๊ฐ๋ฆฌํค๊ธฐ ๋๋ฌธ์ sideEffect๊ฐ ์ฝ๊ฒ ๋ฐ์ํฉ๋๋ค.
๐์๋ฅผ ๋ค์๋ฉด, A ์ ์ ๋ฅผ ํ๋ก์ฐ ํ ํ ๋น์ ์๋๋ก 3์ด๋ง์ B ์ ์ ํ๋กํ๋ก ์ด๋ํ๋ฉด, "B๋ฅผ ํ๋ก์ฐํ์ต๋๋ค" ๋ผ๋ alert ๋ฉ์ธ์ง๊ฐ ๋ํ๋ฉ๋๋ค. (๊ทธ๋ฌ๋ ๋๋ A ์ ์ ๋ฅผ ํ๋ก์ฐ ํ์ต๋๋ค!) `this`๋ mutableํ๋ฉฐ ํ์ฌ์ prop์ ๋ฐ๋ผ๋ณผ ์ ๋ฐ์ ์์ด์ ์๊ธฐ๋ ๋ฌธ์ .
2. ํด๋์คํ ์ปดํฌ๋ํธ์ ์๋ช ์ฃผ๊ธฐ์ ๋ฐ๋ฅธ ์ฌ๋ฌ๊ฐ์ง ๋ฉ์๋๋ฅผ ํจ์ํ ์ปดํฌ๋ํธ์์๋ ํ๋์ ํ ์ด ๋์ฒดํ ์ ์๋ ์ํฉ์ด ๋๋ค๋ณด๋ ํจ์ํ ์ปดํฌ๋ํธ๋ก ๋ง์ด ๋์ด์จ ๊ฒ ๊ฐ๋ค๊ณ ์๊ฐ.