import React from 'react';
ReactDOM.render()
: ๋ธ๋ผ์ฐ์ ์ ์๋ ์ค์ DOM ๋ด๋ถ์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํด์ฃผ๋ ๋ฉ์๋<></>
, ๋ธ๋ผ์ฐ์ ์์ ์ค์ ์๋ฆฌ๋จผํธ๋ก ๋์๋์ง ์์. ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ ๋ฐ๋์ ํ๋์ ํ๊ทธ๋ก ๊ฐ์ธ์ ธ ์์ด์ผ ํ๋๋ฐ, ๋จ์ํ ๊ฐ์ธ๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก ๋ถํ์ํ div๋ฅผ ์ฌ์ฉํ๋ ๋์ Fragment๋ฅผ ์ฌ์ฉํ ์ ์๋ค.background-color โ backgroundColor
const style = {
backgroundColor: 'black',
fontSize: 24
}
<div style={style}>{name}</div>
class
๋์ className
์ผ๋ก ์์ฑ{/* ์ด ์์ */}
์์ฑ (์ค๊ดํธ๋ก ๊ฐ์ธ์ผ ํจ)//
์ฃผ์ ์ฌ์ฉ ๊ฐ๋ฅ (<Hello //์ฃผ์ />
)defaultProps
: ์ปดํฌ๋ํธ์ props๋ฅผ ์ง์ ํ์ง ์์์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ ๊ฐ ์ค์ import React from 'react';
function Hello({ color, name }) {
return <div style={{ color }}>์๋
ํ์ธ์ {name}</div>
}
Hello.defaultProps = {
name: '์ด๋ฆ์์'
}
props.children
: ํ์ ์ปดํฌ๋ํธ๋ฅผ ์กฐํํ๊ณ ์ถ์ ๋ props.children์ ์ฌ์ฉํ๋ค.return <div>{props.children}</div>;
&&
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ ์ฒ๋ฆฌํ๋ค.null
, false
, undefined
๋ฅผ ๋ ๋๋งํ๋ฉด ์๋ฌด๊ฒ๋ ๋ํ๋์ง ์๋๋ค.true
๊ฐ ํ ๋น๋๋ค. (isSpecial === isSpecial={true}
)์ฌ์ฉ์ ์ธํฐ๋์ ์ ๋ฐ๋ผ ๋ฐ๋๋ ๋์ ์ธ ๋ถ๋ถ์ ๊ตฌํํ ๋ state๋ฅผ ์ฌ์ฉํ๋ค.
์๋ ํด๋์คํ ์ปดํฌ๋ํธ์์๋ง ์ํ๋ฅผ ์ฌ์ฉํ ์ ์์์ง๋ง, ๋ฆฌ์กํธ 16.8์์ Hooks์ด ๋์ ๋๋ฉด์, ํจ์ํ ์ปดํฌ๋ํธ์์๋ ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค.
useState
Hook์ ์ด์ฉํด ํจ์ํ ์ปดํฌ๋ํธ์์ state๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค.
Setter ํจ์์ ์ฌ์ฉ :
- ์๋ก์ด state ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ก ๋ฃ์ด์ฃผ๋ ๋ฐฉ์
setValue(value + 1);
setValue(prevValue => prevValue + 1);
์ด๋ฒคํธ ์ฒ๋ฆฌ : onClick={onIncrease()}
X, onClick={onIncrease} OK
(์ ์๋ ๋ ๋๋ง๋๋ ์์ ์์ ํจ์๊ฐ ํธ์ถ๋์ด ๋ฒ๋ฆผ)
์ฌ๋ฌ ๊ฐ์ input ํ๊ทธ ์ํ ๊ด๋ฆฌ :
useState์์ ๋ฌธ์์ด์ด ์๋๋ผ ๊ฐ์ฒด๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๋ค.
input ํ๊ทธ์ name์ ์ค์ ํ๊ณ , ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ์ด ๊ฐ์ ์ฐธ์กฐํ๋ค. (e.target.name: e.target.value
)
๊ฐ์ฒด state๋ฅผ ์์ ํ ๋๋ ์ง์ ์์ ํ๋ฉด ์ ๋๊ณ , ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํด์ผ ํ๋ค.
spread ์ฐ์ฐ์ (...
)๋ฅผ ์ฌ์ฉํด ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํด์ ์ฌ์ฉํ๋ค.
// XXX
inputs[name] = value;
// OOO
setInputs({
...inputs,
[name]: value
});
const nameInput = useRef(); // Ref ๊ฐ์ฒด ์์ฑ
const onReset = () => {
setInputs({
name: '',
nickname: ''
});
nameInput.current.focus(); // Ref ๊ฐ์ฒด์ current ๊ฐ์ผ๋ก ์ ๊ทผ
};
<input
name="name"
onChange={onChange}
value={name}
ref={nameInput} // ref ์ง์
/>
์ปดํฌ๋ํธ ์์์ ์ ๊ทผํ ์ ์๋ ๋ณ์ ๊ด๋ฆฌ :
useRef
๋ก ๊ด๋ฆฌํ๋ ๋ณ์๋ ๊ฐ์ด ๋ฐ๋์ด๋ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋์ง ์๋๋ค.
(ํจ์ํ ์ปดํฌ๋ํธ ๋ด๋ถ์์ useRef
๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ผ๋ฐ ๋ณ์๋ฅผ ์ ์ธํ๋ฉด, ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋๋ง๋ค ๊ฐ์ด ์ด๊ธฐํ ๋๋ค. state๋ฅผ ์ฌ์ฉํ๋ฉด, state ๊ฐ์ด ์ค์ ๋ ๋๋ง๋ค ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋ค.)
๋ฆฌ์กํธ์ state๋ setter๋ฅผ ํธ์ถํ๊ณ ๋์ ๋ ๋๋ง์ด ๋ ์ดํ์ ์
๋ฐ์ดํธ๋ ์ํ๋ฅผ ์กฐํํ ์ ์๋ ๋ฐ๋ฉด,
useRef
๋ก ๊ด๋ฆฌํ๋ ๋ณ์๋ ์ค์ ํ ๋ฐ๋ก ์กฐํํ ์ ์๋ค.
useRef()
๋ฅผ ์ฌ์ฉํ ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฃ์ผ๋ฉด, ์ด ๊ฐ์ด Ref ๊ฐ์ฒด .current
์ ๊ธฐ๋ณธ๊ฐ์ด ๋๋ค.
.current
๋ฅผ ํตํด ๊ฐ์ ์์ ํ๊ฑฐ๋ ์กฐํํ ์ ์๋ค.
const nextId = useRef(4);
const onCreate = () => {
nextId.current += 1;
};
๋ฐฐ์ด์ ์ฌ์ฉํด ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ ค๋ฉด map()
ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
๋ฆฌ์กํธ์์ ๋ฐฐ์ด์ ๋ ๋๋งํ ๋๋ key
props๋ฅผ ๋ฐ๋์ ์ค์ ํด์ผ ํ๋ค.
key
๋ ๊ณ ์ ํ ๊ฐ์ผ๋ก ์ค์ ํด์ผ ํ๋ฉฐ (์ฃผ๋ก id
๊ฐ์ผ๋ก ์ค์ , ์ค๋ณต๋๋ key
๊ฐ ์์ผ๋ฉด ์
๋ฐ์ดํธ๊ฐ ์ ๋๋ก ์ด๋ฃจ์ด์ง์ง ์๋๋ค.) ๋ง์ฝ, key
๋ก ์ค์ ํ ๋งํ ๊ฐ์ด ์๋ค๋ฉด map()
ํจ์์ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์ธ index
๋ฅผ key
๋ก ์ฌ์ฉํ ์ ์๋ค.
key
props๊ฐ ํ์ํ ์ด์ :
key
๊ฐ ์๋ค๋ฉด ๋ฐฐ์ด์ ๋ณ๊ฒฝ ์ฌํญ์ด ์๊ฒจ์ ๋ฆฌ๋ ๋๋ง์ ํ ๋, ๋นํจ์จ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ ๋๋ง์ ํ๊ฒ ๋๋ค. (ex. a, b, d, e ์ฌ์ด์ c๋ฅผ ์ถ๊ฐํ๋ ๊ฒฝ์ฐ, b์ d ์ฌ์ด์ c๋ฅผ ์ถ๊ฐํ๋ ๊ฒ ์๋๋ผ a, b, d -> c, e -> d, e ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฝ์
๋๋ค.)
key
๊ฐ ์์ผ๋ฉด ์์ ๋์ง ์๋ ๊ธฐ์กด์ ๊ฐ์ ๊ทธ๋๋ก ๋๊ณ ์ํ๋ ๋ด์ฉ๋ง ์ฝ์
ํ๊ฑฐ๋ ์ญ์ ํ ์ ์๋ค.
๋ฐฐ์ด์ ํญ๋ชฉ ์ถ๊ฐ / ์ ๊ฑฐ / ์์ ํ๊ธฐ
๋ฐฐ์ด์ ๋ณํ๋ฅผ ์ค ๋์๋ ๊ฐ์ฒด์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ถ๋ณ์ฑ์ ์ง์ผ์ผ ํ๋ค.
push
, splice
, sort
๋ฑ ๊ธฐ์กด ๋ฐฐ์ด์ ์์ ํ๋ ๋ฉ์๋๋ ์ฌ์ฉํ๋ฉด ์ ๋๋ค.
๋ฐฐ์ด์ ํญ๋ชฉ ์ถ๊ฐํ๊ธฐ
...
์ฐ์ฐ์ ์ฌ์ฉ (๊ธฐ์กด ๋ฐฐ์ด์ ํผ์ณ์ ๋ณต์ฌํด ์๋ก์ด ๋ฐฐ์ด์ ๋ด์ ์ ์๋ค.)setUsers([...users, user]);
concat
ํจ์ (๊ธฐ์กด์ ๋ฐฐ์ด์ ์์ ํ์ง ์๊ณ ์๋ก์ด ๋ฐฐ์ด ๋ฐํ)setUsers(users.concat(user));
๋ฐฐ์ด์ ํญ๋ชฉ ์ ๊ฑฐํ๊ธฐ
filter
ํจ์ (๋ฐฐ์ด์์ ํน์ ์กฐ๊ฑด์ด ๋ง์กฑํ๋ ์์๋ค๋ง ์ถ์ถํด ์๋ก์ด ๋ฐฐ์ด์ ์์ฑํจ)setUsers(users.filter(user => user.id !== id));
// id === user.id์ธ ํญ๋ชฉ์ ์ ๊ฑฐ
๋ฐฐ์ด์ ํญ๋ชฉ ์์ ํ๊ธฐ
- ๋ฐฐ์ด์ ์
๋ฐ์ดํธํ ๋๋ map()
ํจ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
const onToggle = id => {
setUsers(
users.map(user =>
user.id === id ? { ...user, active: !user.active } : user
)
);
};
ํด๋นํ๋ id
์ ์ ์ active ๊ฐ์ ๋ฐ์ ์์ผ์ค๋ค.
useEffect
๋ฅผ ์ฌ์ฉํด ์ปดํฌ๋ํธ ๋ง์ดํธ/์ธ๋ง์ดํธ/์
๋ฐ์ดํธ(ํน์ props๊ฐ ๋ฐ๋ ๋) ์ ์ํํ ์์
์ ์ค์ ํ ์ ์๋ค.deps ๋ฐฐ์ด์ด ๋น ๋ฐฐ์ด์ธ ๊ฒฝ์ฐ
useEffect
์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ ์ฝ๋ฐฑ ํจ์, ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ ์์กด๊ฐ ๋ฐฐ์ด(deps
)๋ฅผ ๋ฃ๋๋ค.
deps
๋ฐฐ์ด์ ์๋ ํญ๋ชฉ์ ๊ฐ์ด ๋ฐ๋ ๋๋ง๋ค ์ฝ๋ฐฑ ํจ์๊ฐ ํธ์ถ๋๋ค.
deps
๋ก ๋น ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด, ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋๋ง(์ฒ์ ๋ ๋๋ง๋ ๋) useEffect
์ ๋ฑ๋กํ ํจ์๊ฐ ํธ์ถ๋๋ค.
userEffect
๋ ํจ์๋ฅผ ๋ฐํํ ์ ์๋ค. ์ด ๋ ๋ฐํ๋๋ ํจ์๋ cleanup
ํจ์๋ผ๊ณ ๋ถ๋ฅธ๋ค. deps
๊ฐ ๋น์ด์๋ ๊ฒฝ์ฐ, ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋ cleanup
ํจ์๊ฐ ํธ์ถ๋๋ค.
๋ง์ดํธ / ์ธ๋ง์ดํธ :
props
๋ก ๋ฐ์ ๊ฐ์ ์ปดํฌ๋ํธ์ ๋ก์ปฌ ์ํ๋ก ์ค์ deps ๋ฐฐ์ด์ ๊ฐ์ด ์๋ ๊ฒฝ์ฐ
deps
๋ฐฐ์ด์ ๊ฐ์ ๋ฃ์ผ๋ฉด, ํด๋น ๊ฐ์ด ๋ฐ๋ ๋์๋ useEffect
์ ์ฝ๋ฐฑ ํจ์๊ฐ ํธ์ถ๋๋ฉฐ, ๊ฐ์ด ๋ฐ๋๊ธฐ ์ง์ ์ cleanup
ํจ์๊ฐ ํธ์ถ๋๋ค.
useEffect
์์์ ์ฌ์ฉํ๋ ์ํ๋ props๋ ๋ฐ๋์ deps
์ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด userEffect
์ ๋ฑ๋กํ ํจ์๊ฐ ์คํ๋ ๋ ๊ฐ์ฅ ์ต์ ๊ฐ์ ์ฐธ์กฐํ ๊ฒ์ด๋ผ๊ณ ๋ณด์ฅํ ์ ์๋ค.
deps ๋ฐฐ์ด์ ์๋ตํ ๊ฒฝ์ฐ (=userEffect
์ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ ์๋ต)
const count = countActiveUsers(users);
const count = useMemo(() => countActiveUsers(users), [users];
useMemo
๋ ํน์ (์ฐ์ฐ์) ๊ฒฐ๊ณผ ๊ฐ์ ์ฌ์ฌ์ฉํ ๋, useCallback
์ ํน์ ํจ์๋ฅผ ์ฌ์ฌ์ฉํ ๋ ์ด๋ค.
useCallback
์ useMemo
๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ก๋ค.
(useMemo
๋ก ๋์ฒดํ ์๋ ์๋ค.)
์ปดํฌ๋ํธ ๋ด๋ถ์ ์์ฑํ ํจ์๋ค์ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋๋ง๋ค ์๋ก ์ ์ธ๋๋ค.
ํจ์๋ฅผ ์ ์ธํ๋ ๋ฐ์ ๋ง์ ๋น์ฉ์ด ๋๋ ๊ฑด ์๋์ง๋ง,
๋์ค์ ์ปดํฌ๋ํธ ์ต์ ํ ์์
์ ํ ๋๋ ํจ์์ ์ฌ์ฌ์ฉ์ฑ์ด ํ์์ด๊ธฐ ๋๋ฌธ์ useCallback
์ ์ฌ์ฉํด์ผ ํ๋ค.
ํจ์ ์์์ ์ฌ์ฉ๋๋ props๋ ์ํ๋ ๋ฐ๋์ deps ๋ฐฐ์ด์ ํฌํจ์์ผ์ผ ํ๋ค.
ํจ์ ์์์ state๋ฅผ ์
๋ฐ์ดํธํ ๋, ํจ์ํ ์
๋ฐ์ดํธ๋ฅผ ํ๋ฉด setState์ ๋ฑ๋กํ๋ ์ฝ๋ฐฑํจ์์ ํ๋ผ๋ฏธํฐ์์ ์ต์ state๋ฅผ ์ฐธ์กฐํ ์ ์์ด deps์ state๋ฅผ ๋ฃ์ด์ฃผ์ง ์์๋ ๋๋ค.
React DevTools > ์ค์ > Highlight Updates : ๋ฆฌ๋ ๋๋ง๋๋ ์ปดํฌ๋ํธ๋ฅผ ํ์ธํ ์ ์๋ค.
React.Memo : ์ปดํฌ๋ํธ์ props๊ฐ ๋ฐ๋์ง ์์๋ค๋ฉด, ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋๋ง์ ๋ฐฉ์งํด ์ปดํฌ๋ํธ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ํด์ฃผ๋ ํจ์
(๋ฆฌ๋ ๋๋ง์ด ํ์ํ ์ํฉ์์๋ง ๋ฆฌ๋ ๋๋งํ๋๋ก ์ค์ ํ ์ ์๋ค.)
์ฌ์ฉ ๋ฐฉ๋ฒ์ ์ปดํฌ๋ํธ๋ฅผ export ํ ๋, export default React.memo(component_name)
์ ๊ฐ์ด ๊ฐ์ธ์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
React.memo์ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ์ฝ๋ฐฑ ํจ์ (propsAreEqual
ํจ์)๋ฅผ ์ฌ์ฉํด ํน์ props๋ง ๋น๊ตํ๋ ๊ฒ๋ ๊ฐ๋ฅํ์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์คํ๋ ค ์๋์น ์์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ ์ฃผ์ํด์ผ ํ๋ค.
export default React.memo(
UserList,
(prevProps, nextProps) => prevProps.users === nextProps.users
);
useMemo
, useCallback
, React.memo
๋ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ์ค์ ๋ก ๊ฐ์ ํ ์ ์๋(=์ค์ ๋ก ๋ถํ์ํ ๋ ๋๋ง์ ๋ฐฉ์งํ ์ ์๋) ์ํฉ์์๋ง ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.useReducer
๋ฅผ ํตํด์๋ ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค. useReducer
๋ฅผ ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ์์ ์ํ ์
๋ฐ์ดํธ ๋ก์ง์ ๋ถ๋ฆฌ์ํฌ ์ ์๋ค.React.createContext()
ํจ์๋ฅผ ์ฌ์ฉํด ์๋ก์ด Context๋ฅผ ์์ฑํ๋ค. ํ๋ผ๋ฏธํฐ๋ก๋ Context์ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ ์ ์๋ค.Context ๊ฐ์ฒด ์์๋ Provider๋ผ๋ ์ปดํฌ๋ํธ๊ฐ ๋ค์ด์๋๋ฐ, ์ด ์ปดํฌ๋ํธ๋ฅผ ํตํด ๋ค์๊ณผ ๊ฐ์ด Context์ ๊ฐ์ ์ ํ ์ ์๋ค.
export const AuthContext = React.createContext(null);
<AuthContext.Provider value={dispatch}>
...
</AuthContext.Provider>
// dispatch๋ฅผ Context ๊ฐ์ผ๋ก ์ ํด์ฃผ์ด์ ์ ์ญ์์ dispatch๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
Context ์ฌ์ฉํ๊ธฐ
import React, { useContext } from 'react';
import { AuthContext } from './App';
const User = () => {
const dispatch = useContext(AuthContext);
return (
<div onClick={() => {
dispatch({type: "TOGGLE", id: user.id})}} />
);
};
์ด๋ ๊ฒ useReducer
์ Context API๋ฅผ ๊ฐ์ด ํ์ฉํ๋ฉด
Context API๋ฅผ ์ฌ์ฉํด dispatch
๋ฅผ ์ด๋์๋ ์ง ์กฐํํ ์ ์์ด ์ฝ๋ ๊ตฌ์กฐ๊ฐ ํจ์ฌ ๊น๋ํด์ง๋ค.
๋ฆฌ์กํธ์์ ๋ฐฐ์ด์ด๋ ๊ฐ์ฒด๋ฅผ ์
๋ฐ์ดํธํ ๋ ๋ถ๋ณ์ฑ์ ์งํค๋ ค๋ฉด, ๊ธฐ์กด ๋ฐฐ์ด/๊ฐ์ฒด๋ฅผ ์์ ํ์ง ์๊ณ ์๋ก์ด ๋ฐฐ์ด/๊ฐ์ฒด๋ฅผ ์์ฑํด์ค์ผ ํ๋ค.
๋๋ถ๋ถ์ ๊ฒฝ์ฐ์์๋ ์ด๋ ต์ง ์์ง๋ง, ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๊ฐ ๋ณต์กํด์ง๋ฉด ๋ถ๋ณ์ฑ์ ์งํค๋ฉด์ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์์ฑํด๋ด๋ ์ฝ๋๊ฐ ์กฐ๊ธ ๋ณต์กํด์ง ์ ์๋ค.
Immer๋ฅผ ์ฌ์ฉํ๋ฉด, ์ํ๋ฅผ ์
๋ฐ์ดํธํ ๋ ๋ถ๋ณ์ฑ์ ์ ๊ฒฝ์ฐ์ง ์๊ณ ์ฝ๋๋ฅผ ์์ฑํด๋ Immer๊ฐ ๋ถ๋ณ์ฑ ๊ด๋ฆฌ๋ฅผ ๋์ ํด์ค๋ค.
render()
๋ฉ์๋๊ฐ ๊ผญ ์์ด์ผ ํ๋ค.this.props
๋ก ์ ๊ทผํด์ผ ํ๋ค.import React, { Component } from 'react';
class Hello extends Component {
render() {
const { color, name, isSpecial } = this.props;
}
}
defaultProps
์ค์ ์ ํจ์ํ ์ปดํฌ๋ํธ์ ๋์ผํ ๋ฐฉ์์ผ๋ก ํ ์๋ ์๊ณ , ํด๋์ค ๋ด๋ถ์ static
ํค์๋์ ํจ๊ป ์ ์ธํ ์๋ ์๋ค.class Hello extends Component {
static defaultProps = {
name: '์ด๋ฆ์์'
};
...
}
Hello.defaultProps = {
name: '์ด๋ฆ์์'
};
class Counter extends Component {
handleIncrease() {
console.log('increase');
}
handleDecrease() {
console.log('decrease');
}
// ...
}
์ด๋ ๊ฒ ํด๋์ค ๋ด๋ถ์ ์ข
์๋ ํจ์๋ฅผ ๋ฉ์๋๋ผ๊ณ ๋ถ๋ฅธ๋ค. ํด๋์ค์์ ์ปค์คํ
๋ฉ์๋๋ฅผ ๋ง๋ค ๋๋ ๋ณดํต ์ด๋ฆ์ handle..
๋ก ์ง๋๋ค.
this.setState
๋ผ๋ ํจ์๋ฅผ ์ฌ์ฉํ๋ค.this
๋ ์ปดํฌ๋ํธ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋๋ฐ, ์ปค์คํ
๋ฉ์๋ ์์์ this
๋ฅผ ์กฐํํด๋ณด๋ฉด undefined
๊ฐ ๋์จ๋ค.constructor(props) {
super(props);
this.handleIncrease = this.handleIncrease.bind(this);
this.handDecrease = this.handleDecrease.bind(this);
}
handleIncrease = () => {
console.log('increase');
console.log(this);
};
handleDecrease = () => {
console.log('decrease');
};
ํ์ดํ ํจ์๋ CRA๋ก ๋ง๋ ํ๋ก์ ํธ์๋ ์ ์ฉ์ด ๋์ด ์๋ ๋ฌธ๋ฒ(class-properties ๋ฌธ๋ฒ)์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๊ณ , ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์๋ ์ถ๊ฐ์ ์ธ ์ค์ ์ด ํ์ํ๋ค.
constructor
๋ด๋ถ์์ this.state
๋ฅผ ์ค์ ํด์ฃผ๋ฉด ๋๋ค.constructor(props) {
super(props);
this.state = {
counter: 0
};
}
ํด๋์คํ ์ปดํฌ๋ํธ์ state๋ ๋ฌด์กฐ๊ฑด ๊ฐ์ฒดํํ์ฌ์ผ ํ๋ค.
class-properties ๋ฌธ๋ฒ์ด ์ ์ฉ๋์ด ์๋ค๋ฉด(ex. CRA๋ก ๋ง๋ ํ๋ก์ ํธ) constructor
๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ค์๊ณผ ๊ฐ์ด state๋ฅผ ์ค์ ํ ์ ์๋ค.
class Counter extends Component {
state = {
counter: 0
};
setState
์์๋ useState
์ ๋ง์ฐฌ๊ฐ์ง๋ก ํจ์ํ ์
๋ฐ์ดํธ๋ฅผ ํ ์ ์๋ค.setState
๋ฅผ ์ฌ๋ฌ ๋ฒ์ ๊ฑธ์ณ ํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ ์ฉํ๋ค.setState
๋ ๋จ์ํ ์ํ๋ฅผ ๋ฐ๊พธ๋ ํจ์๊ฐ ์๋๋ผ, ์ํ๋ฅผ ๋ฐ๊ฟ๋ฌ๋ผ๊ณ ์์ฒญํ๋ ํจ์์ด๋ค. ์ฑ๋ฅ ์์ ์ด์ ๋ก ์ํ๊ฐ ๋ฐ๋ก ์
๋ฐ์ดํธ๋์ง ์๊ณ ๋น๋๊ธฐ์ ์ผ๋ก ์
๋ฐ์ดํธ๋๊ธฐ ๋๋ฌธ์ด๋ค. ๋ง์ฝ ์ํ ์
๋ฐ์ดํธ ํ์ ์ด๋ค ์์
์ ํ๊ณ ์ถ๋ค๋ฉด, setState
์ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์ ์ฝ๋ฐฑํจ์๋ฅผ ๋ฃ์ด์ฃผ๊ฑฐ๋, ํจ์ํ ์
๋ฐ์ดํธ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.LifeCycle Method (์๋ช ์ฃผ๊ธฐ ๋ฉ์๋)
LifeCycle Method : ์ปดํฌ๋ํธ๊ฐ ๋ธ๋ผ์ฐ์ ์์ ๋ํ๋๊ณ , ์
๋ฐ์ดํธ๋๊ณ , ์ฌ๋ผ์ง ๋ ํธ์ถ๋๋ ๋ฉ์๋๋ค (+์ปดํฌ๋ํธ์์ ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋ ํธ์ถ๋๋ ๋ฉ์๋๋ ์์)
LifeCycle ๋ฉ์๋๋ ํด๋์คํ ์ปดํฌ๋ํธ์์๋ง ์ฌ์ฉํ ์ ์๋ค.
๋ง์ดํธ :
props
๋ก ๋ฐ์์จ ๊ฐ์ state
์ ๋ฃ์ด์ฃผ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋์ ๋ฐ์ดํธ :
componentDidUpdate
์์ ๋ฐ์์์ ์ฌ์ฉํ ์ ์๋ค.getSanpshotBeforeUpdate
์์ ๋ฐํํ ๊ฐ์ ์กฐํํ ์ ์๋ค.์ธ๋ง์ดํธ :
setTimeout
๋ฑ์ clearํ๊ฑฐ๋, ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ธ์คํด์ค๋ฅผ ์ ๊ฑฐํ๋ค. (= ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ dispose ๊ธฐ๋ฅ์ด ์๋ ๊ฒฝ์ฐ ํธ์ถํ๋ ๊ฒ)function User({ user }) {
if (!user) {
return null;
}
// ...
}
๋คํธ์ํฌ ์์ฒญ์ ํตํ์ฌ ๋์ค์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ฒ ๋๋ ์ํฉ์์๋
์ด๋ ๊ฒ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด null์ ๋ณด์ฌ์ฃผ๊ฑฐ๋, ์๋๋ฉด <div>๋ก๋ฉ์ค</div>
๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ ๋๋งํ๋ฉด ๋๋ค.
props๊ฐ ์ ๋ฌ๋์ง ์์ ์ํฉ์์์ ์๋ฌ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด defaultProps
์ค์ ์ ํด์ค ์๋ ์๋ค.
Users.defaultProps = {
onToggle: () => {
console.warn('onToggle is missing!');
}
};
๋๋ ์ค์๋ก props ์ ๋ฌ์ ๊น๋นกํ์ ๋ ๊ฐ๋ฐ ๋จ๊ณ์์ ๊ฒฝ๊ณ ๋ฅผ ๋ณผ ์ ์๋๋ก PropTypes๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ TypeScript, Flow๋ฅผ ์ฌ์ฉํด ๊ด๋ฆฌํ ์ ์๋ค.
componentDidCatch
๋ฉ์๋๋ฅผ ์ฌ์ฉํด ์ฌ์ ์ ์์ธ์ฒ๋ฆฌ๊ฐ ๋์ง ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ๋ฅผ ํธ๋ค๋งํ ์ ์๋ค. ๊ทธ๋ฌ๋ componentDidCatch๊ฐ ์ค์ ๋ก ํธ์ถ๋๋ ์ผ์ ์๋น์ค์์ ์์ด์ผ ํ๋๊ฒ ๋ง๋ค.
๊ทธ๋ผ์๋ ๋ฐ๊ฒฌํ์ง ๋ชปํ ์๋ฌ๊ฐ ์๋ค๋ฉด, componentDidCatch
์์ error
์ info
๊ฐ์ ๋คํธ์ํฌ๋ฅผ ํตํด ๋ค๋ฅธ ๊ณณ์ผ๋ก ์ ๋ฌํด ํ์ธํ ์ ์๋ค.
์ด๋ฅผ ์ํด ๋ฐ๋ก ์๋ฒ๋ฅผ ๋ง๋๋ ๊ฒ์ ๋ฒ๊ฑฐ๋กญ๊ธฐ ๋๋ฌธ์ Sentry๋ผ๋ ์๋น์ค๋ฅผ ํ๋ก์ ํธ์ ์ ์ฉํ๋ฉด ์ค์๊ฐ์ผ๋ก ์๋ฌ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค.
๋จ, ๋ฐฐํฌ ๋ชจ๋์์๋ componentDidCatch
๋ก ์ก์ ์๋ฌ๊ฐ Sentry์ ์ ๋ฌ๋์ง ์์ผ๋ฏ๋ก, ๋ฐ๋ก ์๋ฌ ๋ฐ์ด๋๋ฆฌ๋ก ์ฒ๋ฆฌํด์ผ ํ๋ค.
componentDidCatch(error, info) {
console.log('์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค.');
console.log({
error,
info
});
this.setState({
error: true
});
if (process.env.NODE_ENV === 'production') {
Sentry.captureException(error, { extra: info });
}
}
process.env.NODE_ENV
๊ฐ์ ์กฐํํด ํ์ฌ ํ๊ฒฝ(๊ฐ๋ฐ ํ๊ฒฝ/๋ฐฐํฌ ํ๊ฒฝ)์ ํ์ธํ ์ ์๋ค.
Sentry์ ์ฐ๋์ ํด๋๋ฉด ๋ฒ๊ทธ ๊ด๋ฆฌ์ ๋งค์ฐ ๋์์ด ๋๋ฏ๋ก ์ฐ๋ํด๋๋ ๊ฒ์ ์ถ์ฒ!
๋ฒจ๋กํผํธ์ ํจ๊ปํ๋ ๋ชจ๋ ๋ฆฌ์กํธ(https://react.vlpt.us)๋ฅผ ์ฐธ๊ณ ํ์ฌ ์์ฑํ ๊ธ์ ๋๋ค.