[๋ฆฌ์กํธ๋ฅผ ๋ค๋ฃจ๋ ๊ธฐ์ ] 7์ฅ - ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋
์ด ๊ธ์ ๊น๋ฏผ์ค(velopert)๋์ ๋ฆฌ์กํธ๋ฅผ ๋ค๋ฃจ๋ ๊ธฐ์ ์์ฐธ์กฐํ์ฌ ์์ฑํ ๊ธ์ ๋๋ค.
๋ชจ๋ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ์๋ ๋ผ์ดํ์ฌ์ดํด(์๋ช ์ฃผ๊ธฐ)์ด ์กด์ฌํ๋ค. ๋ฆฌ์กํธ ํ๋ก์ ํธ๋ฅผ์งํํ๋ค ๋ณด๋ฉด, ์ปดํฌ๋ํธ๋ฅผ ์ฒ์์ผ๋ก ๋ ๋๋งํ ๋ ํน์ ์ปดํฌ๋ํธ๋ฅผ ์ ๋ฐ์ดํธํ๊ธฐ์ ํ๋ก ์ด๋ค ์์ ์ ์ฒ๋ฆฌํด์ผํ ์๋ ์๊ณ , ๋ถํ์ํ ์ ๋ฐ์ดํธ๋ฅผ ๋ฐฉ์งํด์ผ ํ ์๋์๋ค. ์ด๋ ์ปดํฌ๋ํธ์ ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
#
๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋์ ์ดํด๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋๋ ์ด ์ํ ๊ฐ์ง์ด๋ค.
Will ์ ๋์ฌ - ์ด๋ค ์์ ์ ์๋ํ๊ธฐ ์ ์ ์คํ๋๋ ๋ฉ์๋
Did ์ ๋์ฌ - ์ด๋ค ์์ ์ ์๋ํ ํ์ ์คํ๋๋ ๋ฉ์๋
์ด ๋ฉ์๋๋ค์ ์ปดํฌ๋ํธ ํด๋์ค์์ ๋ฎ์ด ์จ ์ ์ธํจ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
๋ผ์ดํ์ฌ์ดํด์ ์ด ์ธ ๊ฐ์ง ๋ง์ดํธ, ์ ๋ฐ์ดํธ, ์ธ๋ง์ดํธ๋ก ๋๋๋ค.
๋ง์ดํธ : ํ์ด์ง์ ์ปดํฌ๋ํธ๊ฐ ๋ํ๋จ
์ ๋ฐ์ดํธ : ์ปดํฌ๋ํธ ์ ๋ณด๋ฅผ ์ ๋ฐ์ดํธ(๋ฆฌ๋ ๋๋ง)
์ธ๋ง์ดํธ : ํ์ด์ง์์ ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ผ์ง
#
๋ง์ดํธDOM์ด ์์ฑ๋๊ณ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ํ๋๋ ๊ฒ์ ๋ง์ดํธ(mount)๋ผ๊ณ ํ๋ค. ์ด ๋ ๋ค์์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ
constructor
๋ฉ์๋ : ์ปดํฌ๋ํธ๋ฅผ ์๋ก ๋ง๋ค ๋๋ง๋ค ํธ์ถ๋๋ ํด๋์ค ์์ฑ์ ๋ฉ์๋getDerivedStateFromProps
๋ฉ์๋ :props
์ ์๋ ๊ฐ์state
์ ๋ฃ์ ๋์ฌ์ฉํ๋ ๋ฉ์๋render
๋ฉ์๋ : ์ค๋นํ UI๋ฅผ ๋ ๋๋งํ๋ ๋ฉ์๋componentDidMount
๋ฉ์๋ : ์ปดํฌ๋ํธ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ํ๋ ํ์ ํธ์ถํ๋๋ฉ์๋
#
์ ๋ฐ์ดํธ์ปดํฌ๋ํธ๋ ๋ค์์ ๊ฒฝ์ฐ์ ์ ๋ฐ์ดํธํ๋ค.
props
๊ฐ ๋ฐ๋ ๋state
๊ฐ ๋ฐ๋ ๋๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋
this.forceUpdate
๋ก ๊ฐ์ ๋ก ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํ ๋
์ด๋ฌํ ๊ฒฝ์ฐ๋ก ์ปดํฌ๋ํธ๋ฅผ ์ ๋ฐ์ดํธํ๊ฒ ๋๋ฉด ๋ค์์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
์ปดํฌ๋ํธ ์ ๋ฐ์ดํธ
getDerivedStateFromProps
๋ฉ์๋ :props
์ ์๋ ๊ฐ์state
์ ๋ฃ์ ๋์ฌ์ฉํ๋ ๋ฉ์๋ (๋ง์ดํธ์์๋ ํธ์ถ๋จ)shouldComponentUpdate
๋ฉ์๋ : ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง์ ํด์ผ ํ ์ง ๋ง์์ผ ํ ์ง๋ฅผ ๊ฒฐ์ ํ๋ ๋ฉ์๋ (true
๋ฅผ ๋ฐํํ๋ฉด ๋ฆฌ๋ ๋๋ง,false
๋ฉด ๋ฆฌ๋ ๋๋ง ํ์ง ์์.)render
๋ฉ์๋ : ์ค๋นํ UI๋ฅผ ๋ ๋๋งํ๋ ๋ฉ์๋getSnapshotBeforeUpdate
: ์ปดํฌ๋ํธ ๋ณํ๋ฅผ DOM์ ๋ฐ์ํ๊ธฐ ์ง์ ์ ํธ์ถํ๋ ๋ฉ์๋componentDidUpdate
: ์ปดํฌ๋ํธ์ ์ ๋ฐ์ดํธ ์์ ์ด ๋๋ ํ ํธ์ถํ๋ ๋ฉ์๋
#
์ธ๋ง์ดํธ์ปดํฌ๋ํธ๋ฅผ DOM์์ ์ ๊ฑฐํ๋ ๊ฒ์ ์ธ๋ง์ดํธ(unmount)๋ผ๊ณ ํ๋ค. ์ปดํฌ๋ํธ๋ฅผ ์ธ๋ง์ดํธํ๋ฉด ๋ค์์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
componentWIllUnmount
: ์ปดํฌ๋ํธ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์์์ ์ฌ๋ผ์ง๊ธฐ ์ ์ ํธ์ถํ๋๋ฉ์๋
#
๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋ ์ดํด๋ณด๊ธฐrender
#
์ปดํฌ๋ํธ์ ๋ชจ์์๋ฅผ ์ ์ํ๋ ๋ฉ์๋. ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋ ์ค ์ ์ผํ ํ์ ๋ฉ์๋์ด๋ค.
์ด ๋ฉ์๋ ์์์ this.props
์ this.state
์ ์ ๊ทผํ ์ ์๋ค.
์ด ๋ฉ์๋ ์์์ ์ด๋ฒคํธ ์ค์ ์ด ์๋ ๊ณณ์์ setState
๋ฅผ ์ฌ์ฉํด์ ์๋๊ณ , ๋ธ๋ผ์ฐ์ ์ DOM์ ์ ๊ทผํด์๋ ์๋๋ค. DOM ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ state
์ ๋ณํ๋ฅผ ์ค ๋๋ componentDidMount
์์ ์ฒ๋ฆฌํด์ผ ํ๋ค.
constructor
#
์ปดํฌ๋ํธ์ ์์ฑ์ ๋ฉ์๋๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋ ์ฒ์์ผ๋ก ์คํ๋๋ค. ์ด๊ธฐ state
๋ฅผ์ ํ ์ ์๋ค.
getDerivedStateFromProps
#
props
๋ก ๋ฐ์ ์จ ๊ฐ์ state
์ ๋๊ธฐํ์ํค๋ ์ฉ๋.
static getDerivedStateFromProps(nextProps, prevState) { if(nextProps.value !== prevState.value) { return { value: nextProps.value }; } return null;}
componentDidMount
#
์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ ์ฒซ ๋ ๋๋ง์ ๋ง์น ํ ์คํํ๋ค. ์ด ์์์ ๋ค๋ฅธ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ ํ๋ ์์ํฌ์ ํจ์๋ฅผ ํธ์ถํ๊ฑฐ๋ ์ด๋ฒคํธ ๋ฑ๋ก, setTimeout
, setInterval
, ๋คํธ์ํฌ ์์ฒญ ๊ฐ์ ๋น๋๊ธฐ ์์
์ ์ฒ๋ฆฌํ๋ฉด ๋๋ค.
shouldComponentUpdate
#
props
๋๋ state
๋ฅผ ๋ณ๊ฒฝํ์ ๋ ๋ฆฌ๋ ๋๋ง์ ์์ํ ์ง ์ฌ๋ถ๋ฅผ ์ง์ ํ๋ ๋ฉ์๋. ์ด ๋ฉ์๋๋ฅผ ๋ฐ๋ก ์์ฑํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก true
๋ฅผ ๋ฐํํด์ ์ธ์ ๋ ๋ฆฌ๋ ๋๋ง์ํ๋ค. false
๋ฅผ ๋ฐํํ๋ฉด ์
๋ฐ์ดํธ ๊ณผ์ ์ด ์ฌ๊ธฐ์ ์ค์ง๋๋ค. (๋ฆฌ๋ ๋๋ง๋์ง ์๋๋ค .)
getSnapshotBeforeUpdate
#
render
์์ ๋ง๋ค์ด์ง ๊ฒฐ๊ณผ๋ฌผ์ด ๋ธ๋ผ์ฐ์ ์ ์ค์ ๋ก ๋ฐ์๋๊ธฐ ์ง์ ์ ํธ์ถ. ์ฃผ๋ก ์
๋ฐ์ดํธ ์ง์ ์ ๊ฐ์ ์ฐธ๊ณ ํ ์ผ์ด ์์ ๋ ํ์ฉ๋๋ค.
getSnapshotBeforeUpdate(prevProps, prevState) { if(prevState.array !== this.state.array) { const { scrollTop, scrollHeight } = this.list return { scrollTop, scrollHeight }; }}
componentDidUpdate
#
componentDidUpdate(prevProps, prevState, snapshot){...}
๋ฆฌ๋ ๋๋ง์ ์๋ฃํ ํ ์คํํ๋ค. prevProps
๋๋ prevState
๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๊ฐ ์ด์ ์ ๊ฐ์ก๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๋ค. ๋ํ getSnapshotBeforeUpdate
์์ ๋ฐํํ ๊ฐ์ด ์๋ค๋ฉด ์ฌ๊ธฐ์ snapshot
๊ฐ์ ์ ๋ฌ๋ฐ์ ์ ์๋ค.
componentWillUnmount
#
์ปดํฌ๋ํธ๋ฅผ DOM์์ ์ ๊ฑฐํ ๋ ์คํ. componentDidMount
์์ ๋ฑ๋กํ ์ด๋ฒคํธ, ํ์ด๋จธ, ์ง์ ์์ฑํ DOM์ด ์๋ค๋ฉด ์ฌ๊ธฐ์ ์ ๊ฑฐ ์์
์ ํด์ผํ๋ค.
componentDidCatch
#
์ปดํฌ๋ํธ ๋ ๋๋ง ๋์ค์ ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋จนํต์ด ๋์ง ์๊ณ ์ค๋ฅ UI๋ฅผ ๋ณด์ฌ์ค ์ ์๊ฒ ํด์ค๋ค.
componentDidCatch(error, info) { this.setState({ error: true }); console.log({ error, info });}
error
ํ๋ผ๋ฏธํฐ๋ ์ด๋ค ์๋ฌ๊ฐ ๋ฐ์ํ๋์ง ์๋ ค์ฃผ๊ณ info
ํ๋ผ๋ฏธํฐ๋ ์ด๋์ ์๋์ฝ๋์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋์ง์ ๋ํ ์ ๋ณด๋ฅผ ์ค๋ค.
#
๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋ ์ฌ์ฉํ๊ธฐLifeCycleSample.js
๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ ๋ค.
import React, {Component} from 'react';
class LifeCycleSample extends Component { state = { number: 0, color: null, };
myRef = null;
constructor(props) { super(props); console.log('constructor'); }
static getDerivedStateFromProps(nextProps, prevState) { console.log('getDerivedStateFromProps'); if (nextProps.color !== prevState.color) { return {color: nextProps.color}; } return null; }
componentDidMount() { console.log('componentDidMount'); }
shouldComponentUpdate(nextProps, nextState) { console.log('shouldComponentUpdate', nextProps, nextState); return nextState.number % 10 !== 4; }
componentWillUnmount() { console.log('componentWillUnmount'); }
handleClick = () => { this.setState({ number: this.state.number + 1, }); };
getSnapshotBeforeUpdate(prevProps, prevState) { console.log('getSnapshotBeforeUpdate'); if (prevProps.color !== this.props.color) { return this.myRef.style.color; } return null; }
componentDidUpdate(prevProps, prevState, snapshot) { console.log('componentDidUpdate', prevProps, prevState); if (snapshot) { console.log('์
๋ฐ์ดํธ ๋๊ธฐ ์ง์ ์์: ', snapshot); } }
render() { console.log('render');
const style = { color: this.props.color, };
return ( <div> <h1 style={style} ref={(ref) => (this.myRef = ref)}> {this.state.number} </h1> <p>color:{this.state.color}</p> <button onClick={this.handleClick}>๋ํ๊ธฐ</button> </div> ); }}
export default LifeCycleSample;
์ด ์ปดํฌ๋ํธ๋ ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋๋ฅผ ์คํํ ๋๋ง๋ค ์ฝ์ ๋๋ฒ๊ฑฐ์ ๊ธฐ๋กํ๊ณ ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ props
๋ก ์์์ ๋ฐ๊ณ , ๋ฒํผ์ ๋๋ฅด๋ฉด state.number
๊ฐ์ 1์ฉ ๋ํ๋ค.
shouldComponentUpdate
๋ฉ์๋์์ state.number
๊ฐ์ ๋ง์ง๋ง ์๋ฆฌ ์๊ฐ 4์ด๋ฉด ๋ฆฌ๋ ๋๋ง์ ์ทจ์ํ๋๋ก ์ค์ ํ๋ค.
App.js
import React, {Component} from 'react';import LifeCycleSample from './LifeCycleSample';
function getRandomColor() { return '#' + Math.floor(Math.random() * 16777215).toString(16);}class App extends Component { state = { color: '#000000', }; handleClick = () => { this.setState({ color: getRandomColor(), }); }; render() { return ( <div> <button onClick={this.handleClick}>๋๋ค ์์</button> <LifeCycleSample color={this.state.color} /> </div> ); }}export default App;
์ฝ๋๋ฅผ ์ ์ฅํ๋ฉด ๋ค์ ๊ฒฐ๊ณผ๊ฐ ๋ํ๋๋ค.
์์ชฝ ๋ฒํผ๊ณผ ์๋์ชฝ ๋ฒํผ์ ๋ฒ๊ฐ์ ๋๋ฅด๋ฉด ์๋์ฒ๋ผ ๋ํ๋๋ค.
#
์๋ฌ ์ก์๋ด๊ธฐrender
ํจ์์์ ์กด์ฌํ์ง ์๋ ํจ์๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๊ฑฐ๋, ์กด์ฌํ์ง ์๋ ๊ฐ์ฒด์๊ฐ์ ์กฐํํ ๋ ๋ฐ์ํ๋ค.
LifeCycleSample.js
render() { console.log('render');
const style = { color: this.props.color, };
return ( <div> {this.props.missing.value} <h1 style={style} ref={(ref) => (this.myRef = ref)}> {this.state.number} </h1> <p>color:{this.state.color}</p> <button onClick={this.handleClick}>๋ํ๊ธฐ</button> </div> );}
์ด๋ ๊ฒ ์กด์ฌํ์ง ์๋ props
์ธ missing
๊ฐ์ฒด์ value
๋ฅผ ์กฐํํด์ ๋ ๋๋งํ๋ ค๊ณ ํ๋ฉด ๋ธ๋ผ์ฐ์ ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
์ค๋ฅธ์ชฝ ์์ X ๋ฒํผ์ ๋๋ฅด๋ฉด ์ค๋ฅ ์ฐฝ์ด ๋ซํ๊ณ ๋ธ๋ผ์ฐ์ ์๋ ์๋ฌด๊ฒ๋ ์๋ ํฐ ํ์ด์ง๋ง ๋จ๋๋ค. ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋ ๋ฐ๋ก ์ฒ๋ฆฌํด์ฃผ์ง ์์ผ๋ฉด ์ด๋ ๊ฒ ๋น ํ์ด์ง๋ง ๋จ์์ฌ์ฉ์๋ฅผ ๋นํฉ์ํค๊ฒ ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ErrorBoundary
๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํด๋ณธ๋ค.
ErrorBoundary.js
import React, {Component} from 'react';
class ErrorBoundary extends Component { state = { error: false, };
componentDidCatch(error, info) { this.setState({ error: true, }); console.log({error, info}); } render() { if (this.state.error) return <div>์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค!</div>; return this.props.children; }}
export default ErrorBoundary;
์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด componentDidCatch
๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉฐ, this.state.error
๊ฐ์ true
๋ก ์
๋ฐ์ดํธํด์ค๋ค. ๊ทธ๋ฌ๋ฉด render
์์ ์๋ฌ๊ฐ ๋ฐ์ํ์์ ์๋ ค์ฃผ๋ ๋ฌธ๊ตฌ๋ฅผ๋ณด์ฌ์ค๋ค.
์ด ์ปดํฌ๋ํธ๋ฅผ App.js
์์ LifeCycleSample
์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ธ์ค๋ค.
App.js
import React, {Component} from 'react';import LifeCycleSample from './LifeCycleSample';import ErrorBoundary from './ErrorBoundary';
function getRandomColor() { return '#' + Math.floor(Math.random() * 16777215).toString(16);}class App extends Component { state = { color: '#000000', }; handleClick = () => { this.setState({ color: getRandomColor(), }); }; render() { return ( <div> <button onClick={this.handleClick}>๋๋ค ์์</button> <ErrorBoundary> <LifeCycleSample color={this.state.color} /> </ErrorBoundary> </div> ); }}export default App;
์ฌ์ ํ ์๋ฌ๊ฐ ๋ฐ์ํ์ง๋ง, X ๋ฒํผ์ ๋๋ฅธ ๋ค ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ณด๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ์ ์๋ ค์ฃผ๋ ํ์ด์ง๋ฅผ ๋ณผ ์ ์๋ค.
#
์ ๋ฆฌ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋๋ ์ปดํฌ๋ํธ ์ํ์ ๋ณํ๊ฐ ์์ ๋๋ง๋ค ์คํํ๋ ๋ฉ์๋์ด๋ค. ์ด๋ฉ์๋๋ค์ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ DOM์ ์ง์ ๊ฑด๋๋ ค์ผ ํ๋ ์ํฉ์์ ์ ์ฉํ๋ค. ์ปดํฌ๋ํธ ์
๋ฐ์ดํธ์ ์ฑ๋ฅ์ ๊ฐ์ ํ ๋๋ shouldComponentUpdate
๊ฐ ์ค์ํ๊ฒ ์ฌ์ฉ๋๋ค.