import React from 'react';ReactDOM.render() : ๋ธ๋ผ์ฐ์ ์ ์๋ ์ค์ DOM ๋ด๋ถ์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํด์ฃผ๋ ๋ฉ์๋<></>, ๋ธ๋ผ์ฐ์ ์์ ์ค์ ์๋ฆฌ๋จผํธ๋ก ๋์๋์ง ์์. ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ ๋ฐ๋์ ํ๋์ ํ๊ทธ๋ก ๊ฐ์ธ์ ธ ์์ด์ผ ํ๋๋ฐ, ๋จ์ํ ๊ฐ์ธ๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก ๋ถํ์ํ div๋ฅผ ์ฌ์ฉํ๋ ๋์ Fragment๋ฅผ ์ฌ์ฉํ ์ ์๋ค.background-color โ backgroundColorconst 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)๋ฅผ ์ฐธ๊ณ ํ์ฌ ์์ฑํ ๊ธ์ ๋๋ค.