ėëĄęē ėęē ë ëīėĐėīęą°ë ėīíīíęļ° ėīë Īė ë ëķëķë§ ė ëĶŽ
ė―ëë Using the Effect Hook íėīė§ ė°ļęģ
2) & 3)ė [TIL] 220125ë íĻęŧ ė°ļęģ
íëĄę·ļëë°ėė side effect(ëë effect)ë, ėīëĪ íĻėę° íĻė ėļëķė ė ëģīė ėíĨė ėĢžęģ ë°ë ėž
ė ë§íëĪ.
ėëĨž ëĪėī, Reactėė íĻė ėŧīíŽëíļë ëëĄ UIė ę·ļë ĪėĪ ë°ėīí°ëĨž ėļëķėė ę°ė ļėėž í ėë ėëë°, ėī ęē―ė° ėëēė ęĩëĨíë ëĪíļėíŽ ėėēė side effectëžęģ í ė ėëĪ.
ę·ļë°ë° ėīëŽí ėėēė ėēė í ëēë§ íėíęģ íĻė ėŧīíŽëíļę° ë ëë§ ë ëë§ëĪ ėėēí íėë ėë ęē―ė°ę° ë§ëĪ.
useEffect()ëĨž ėŽėĐíëĐī íĻė ėŧīíŽëíļėė ėī ę°ė side effectëĨž íĻėĻė ėžëĄ ėíí ė ėëĪ.
ë°ėīí° ę°ė ļėĪęļ° ėļėë ęĩŽë (subscription) ėĪė í ę·ļëĶŽęģ ėėė ėīíīëģļ ėëėžëĄ React ėŧīíŽëíļė DOM ėė íęļ° ëí side effectė íīëđíëĪ.
side effect ėĪėė ëĪíļėíŽ ėėē
, DOM ėë ėĄ°ė
, ëĄęđ
ëąė ė ëĶŽ(clean-up)ę° íėėëĪ.
render ëĐėë ę·ļ ėėēīë side effectëĨž ë°ėėíĪė§ ėëëĪ.
side effectë Reactę° DOMė ė
ë°ėīíļ í íė ėíëëĪ.
React classėė side effectë componentDidMount
ė componentDidUpdate
ėė ėíëëĪ.
React class ėėė 2ę°ė ėëŠ ėĢžęļ° ëĐėëė ę°ė ė―ëę° ë°ëģĩëëë°, ėīëĨž ę°ė í ë°Đëēėī ėęļ° ëëŽļė ėĪëģĩ ė―ëëĨž ėŽėĐíīėž íëĪ.
React classėėė ë§ė°Žę°ė§ëĄ side effectę° ėíëë ėė ė ėīëŊļ DOMėī ė
ë°ėīíļ ëėė
ė ëģīėĨíëĪ.
useEffect()ę° ėēŦ ëēė§ļ ėļėëĄ ë°ë íĻėëĨž 'effect'ëžęģ ëķëĨļëĪ.
Reactë ėŧīíŽëíļ ë ëë§ ė ėī íĻėëĨž ęļ°ėĩíëĪę° DOM ė
ë°ėīíļęđė§ ëë íė ėī íĻėëĨž ëķëŽëļëĪ.
effect íĻėë (ë ëēė§ļ ėļė ėėī ėŽėĐíëĐī) ęļ°ëģļė ėžëĄ ėēŦ ëēė§ļ ë ëë§ė ëđëĄŊíī ėīíė ëŠĻë ėŧīíŽëíļ ė
ë°ėīíļ ėė ėĪíëëĪ.
React classėėė ëŽëĶŽ ėīëĨž ëë ėėąíė§ ėėë ëęļ° ëëŽļė ėĪëģĩ ė―ëëĨž ėŽėĐí íėę° ėëĪ.
side effect ėĪėė ęĩŽë
ė ėĪė íë ęē
(ex.ėīëēĪíļ ęĩŽë
ëą)ė ëĐëŠĻëĶŽ ëėëĨž ë°Đė§íęļ° ėíī ė ëĶŽ(clean-up)ëĨž íėëĄ íëĪ.
React classėė side effectë componentDidMount
ė componentDidUpdate
ėė ėíëęģ , componentWillUnmount
ėė ė ëĶŽ(clean-up)ëëĪ.
ę·ļë°ë° ėīė ę°ė ėëŠ ėĢžęļ° ëĐėëëĪė ę°ë ė ëę°ė effect ė―ëëĨž ę°ė§ęģ ėėėë React classėėë ë§Īëē ėĪëģĩėžëĄ ėėąíīėžë§ íëĪ.
useEffect()ė ėēŦ ëēė§ļ ėļėėļ effect íĻėę° cleanup íĻėëĨž return íëëĄ ėėąíëĐī ėŧīíŽëíļę° ë§ėīíļ íīė ëėī ė ëĶŽę° íėí ë cleanup íĻėę° ėĪíëëĪ.
cleanup íĻėëĄë ė ëŠ
íĻėë ėĩëŠ
íĻėë íėīí íĻėë ėęīėëĪ.
íĻė ėŧīíŽëíļ (ëë íĻė ėŧīíŽëíļę° íļėķíë íĻė ėŧīíŽëíļ)ę° props, state ëë íėë ę°ė ė°ļėĄ°íė§ ėë
ęē―ė°ėë
ėĒ ėėą ëŠĐëĄėė íĻė ėŧīíŽëíļëĨž ėëĩíīë ėė íëĪ.
function Example() {
// ~ëĨž ė°ļėĄ°íė§ ėë íĻė ėŧīíŽëíļë effect ėļëķė ė ėļíīë ok
function doSomething() {
console.log('hello');
}
useEffect(() => {
doSomething();
}, []); // ėĒ
ėėą ëŠĐëĄėė íĻė ėŧīíŽëíļ ėëĩ ok
}
function Example() {
useEffect(() => {
// ~ëĨž ė°ļėĄ°íė§ ėë íĻė ėŧīíŽëíļë effect ëīëķė ė ėļíīë ok
function doSomething() {
console.log('hello');
}
doSomething();
}, []); // ėĒ
ėėą ëŠĐëĄėė íĻė ėŧīíŽëíļ ėëĩ ok
}
íĻė ėŧīíŽëíļ (ëë íĻė ėŧīíŽëíļę° íļėķíë íĻė ėŧīíŽëíļ)ę° props, state ëë íėë ę°ė ė°ļėĄ°íë
ęē―ė°ėë
ę·ļ íĻė ėŧīíŽëíļëĨž effect ëīëķė ė ėļ
íęģ ė°ļėĄ°íë props ëë stateëĨž ėĒ
ėėą ë°°ėīė ėķę°íīėž íëĪ.
ë§ė― ėīëĪ ėīė ëĄ íĻė ėŧīíŽëíļëĨž effect ëīëķëĄ ėīëí ė ėęģ effect ėļëķė ëėīėž íëĪëĐī
, useEffect() ėĒ
ėėą ëŠĐëĄė íīëđ íĻė ėŧīíŽëíļëĨž ėķę°íë(ėëĩ X), effect ėļëķė ėėđí ę·ļęēė ė ė ëķëķė useCallback()ėžëĄ ę°ėļėž íëĪ.
function ProductPage({ productId }) {
// effect ėļëķė ėėđí íĻė ėŧīíŽëíļė ė ė ëķëķė useCallback()ėžëĄ ę°ėžëĪ
// 'propsëĨž ė°ļėĄ°íë' íĻė ėŧīíŽëíļę° effect 'ėļëķ'ė ėėđíī ėėžëŊëĄ
const fetchProduct = useCallback(() => {
// ...
}, [productId]);
return <ProductDetails fetchProduct={fetchProduct} />;
}
function ProductDetails({ fetchProduct }) {
useEffect(() => {
fetchProduct();
}, [fetchProduct]); // íīëđ íĻė ėŧīíŽëíļëĨž useEffect() ėĒ
ėėą ëŠĐëĄėė ėëĩíīė ėëëĪ
// ...
}
ėīë ęē íëĐī ProductPageėė productId propėī ëģęē―ëëĐī
ProductDetails ėŧīíŽëíļėė ėëėžëĄ ëĪė ę°ė ļėĪęļ°ę° íļëĶŽęą° ëëĪ.(fetchProduct íĻė ėĪí)
function Counter() {
const [count, setCount] = useState(0);
// console.log(count); // ėēė ë ëë§ ė 0, ę·ļ ėīíëĄ ęģė 1
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1); // effectę° count stateė ėėĄīíĻėë ëķęĩŽíęģ
}, 1000);
return () => clearInterval(id);
}, []); // ėĒ
ėėą ëŠĐëĄė countëĨž ėëĩíëĪ => ëēę·ļ â
return <h1>{count}</h1>;
}
ReactDOM.render(<Counter />, document.getElementById("root"));
ėļëķ íĻėėļ Counter íĻėė count stateë ëīëķ íĻėėļ setIntervalė ė―ë°ą íĻėėė ė°ļėĄ°íęģ ėęļ° ëëŽļė íīëĄė ëĨž íėąíęē ëëĪ.
ęē°ęĩ 1ėīę° ė§ë ëë§ëĪ setCount(count + 1) ėĪí ė íīëĄė ëĄ ėļíī ë§Īëē count stateė ėīęđę° 0ė ę°ė ļėĪęē ëėī ęē°ęģžė ėžëĄ countė ę°ė 1ëĄ ë°ęŋ ëŋėīęģ , ëŠ ėīę° ė§ëëëžë countė ę°ėī ę·ļ ėīėė ėīęģží ėë ėëĪ.
ëēę·ļëĨž íīęē°íęļ° ėíī ėĒ
ėėą ëŠĐëĄė count stateëĨž ėķę°í ė ėëĪ.
ę·ļë°ë° ę·ļë ęē ëëĐī count stateė ę°ėī ë§Īėīë§ëĪ ëģíęļ°ë íė§ë§, ėīë ėŽėĪ ė ëëĄ ė―ëëĨž ėėąíëĪëĐī setIntervalė í ëēë§ íļėķíëĐī ëë ęēė, ë§Īėīë§ëĪ count stateę° ë°ëė ë°ëž setIntervalė ëĪė íļėķíęē ëėī ë°ëė§íė§ ėëĪ.
ę°ėĨ ėĩė ė ë°Đëēė setState íĻėė ėļėëĄ 'ė―ë°ą íĻė'ëĨž ëĢėīėĢžë ęē
ėīëĪ.
function Counter() {
const [count, setCount] = useState(0);
// console.log(count); // 0, 1, 2, 3... ė ėė ėžëĄ ė
ë°ėīíļę° ëëĪ
useEffect(() => {
const id = setInterval(() => {
setCount(c => c + 1); // ð effectę° count stateė ėėĄī X, ėīė stateëĨž ë°íėžëĄ ėëĄėī stateëĨž ëėķ
}, 1000);
return () => clearInterval(id);
}, []); // ėĒ
ėėą ëŠĐëĄė count ėëĩ => setIntervalė ėēė ë ëë§ ė 1ëēë§ íļėķëĻ
return <h1>{count}</h1>;
}
ReactDOM.render(<Counter />, document.getElementById("root"));
const [state, dispatch] = useReducer(reducer, initialArg, init);
useReducerė ėēŦ ëēė§ļ ėļėë (state, action) => newStateė ííëĨž ę°ė§ë reducer íĻė
ėīëĪ.
ėīë reducer íĻėė ë ëēė§ļ ėļėėļ actionė ė
ë°ėīíļëĨž ėí ė ëģīëĨž ę°ė§ë ę°ėēīėīëĪ.
dispatchë ėĄė
ė ë°ėėíĪë íĻėëĄėĻ, reducer íĻėë dispatch íĻėę° ë°ėėíĻ ėĄė
ė ë°ëž stateëĨž ë°ííëĪ.
reducer íĻėę° ë°ííë ėëĄėī stateę° ęģ§ ėŧīíŽëíļėė ėŽėĐë stateę° ëëĪ.
useReducerė ë ëēė§ļ ėļėë stateė ėīęđę°
ė ë°ëëĪ.
useReducerė ėļ ëēė§ļ ėļėë ėīęđę°ė ėĪė íë íĻė
ëĨž ë°ëëĪ.
ėīë ëėĪė stateëĨž ėŽėĪė
íë ë°ë ėŽėĐí ė ėëĪ.
function init(initialCount) {
return {count: initialCount};
}
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
case 'reset':
return init(action.payload);
default:
throw new Error();
}
}
function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}>
Reset
</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
componentDidMountė componentDidUpdateėë ëŽëĶŽ useEffect()ëĄ ė ëŽë íĻė, ėĶ effect íĻėë ė§ė° ėīëēĪíļ ëėė ë ėīėė ë°°ėđė ę·ļëĶŽęļ°ëĨž ėëĢí íė ë°ėíëĪ.
ėīë ęĩŽë
ėīë ėīëēĪíļ íļëĪëŽ ėĪė ëąė side effectę° ëļëžė°ė ėė íëĐīė ė
ë°ėīíļíë ęēė ė°ĻëĻíīėë ė ëëŊëĄ ëëķëķė ęē―ė° ë°ëė§íëĪ.
ę·ļëŽë, ėŽėĐėėęē ë
ļėķëë DOM ëģęē―
ęģž ę°ė side effectë íëĐīė ė
ë°ėīíļę° ëëęļ° ė ė ëęļ°íę° ėëĢëėīėž íëĪ.
ėīëŽí side effectëĨž ėíī useLayoutEffect()
ëĨž ėŽėĐí ė ėëĪ.
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
useCallbackė ëĐëŠĻėīė ėīė
ë ė―ë°ąė ë°í
íëĪ.
ėēŦ ëēė§ļ ėļėëĄë ė―ë°ą íĻėëĨž, ë ëēė§ļ ėļėëĄë ėĒ ėėą ëŠĐëĄ(ėėĄīėą ę°ė ë°°ėī)ė ë°ëëĪ.
ëĶŽë ëë§ ėė ėĒ ėėą ëŠĐëĄėī ëģęē―ëė§ ėë í ëĐëŠĻėīė ėīė ë ė―ë°ą ëí ëģęē―ëė§ ėëëĪ.
ė°ļėĄ°ė ëėžėąė ėėĄīė ėļ ėĩė íë ėė ėŧīíŽëíļė ė―ë°ąė ė ëŽí ë ė ėĐíëĪ. ( ėŽęļ° ė°ļęģ )