Post

🌌 React μž…λ¬Έ β…§ - Hook

🌌 React μž…λ¬Έ β…§ - Hook

πŸ“˜ γ€Žμ†Œν”Œμ˜ 처음 λ§Œλ‚œ λ¦¬μ•‘νŠΈγ€λ₯Ό 읽고 μ •λ¦¬ν•œ κΈ€μž…λ‹ˆλ‹€.

Hookμ΄λž€?

  • 기쑴의 Functional ComponentλŠ”Class Componentμ™€λŠ” λ‹€λ₯΄κ²Œ μ½”λ“œλ„ ꡉμž₯히 κ°„κ²°ν•˜κ³  λ³„λ„λ‘œΒ Stateλ₯Ό μ •μ˜ν•˜κ±°λ‚˜ Component의 생λͺ…μ£ΌκΈ° ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†μ—ˆλ‹€.
  • 이런 κΈ°λŠ₯을 μ§€μ›ν•˜κΈ° μœ„ν•΄ λ‚˜μ˜¨ 것이 λ°”λ‘œ Hook이닀.
  • Hookμ΄λΌλŠ” λ‹¨μ–΄λŠ” 갈고리λ₯Ό λœ»ν•˜λŠ”λ°, 갈고리λ₯Ό κ±°λŠ” κ²ƒμ²˜λŸΌ μ›λž˜ μ‘΄μž¬ν•˜λŠ” μ–΄λ–€ κΈ°λŠ₯에 끼어 λ“€μ–΄κ°€ 같이 μˆ˜ν–‰ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€.
  • Hook의 이름은 λͺ¨λ‘Β use둜 μ‹œμž‘ν•œλ‹€.
  • κ°œλ°œμžκ°€ 직접 Custom Hook을 λ§Œλ“€μ–΄ μ‚¬μš©ν•  경우 이름을 λ§ˆμŒλŒ€λ‘œ 지을 μˆ˜λ„ μžˆμ§€λ§Œ useλ₯Ό λͺ…μ‹œν•΄ μ£ΌλŠ” 것이 μ˜¬λ°”λ₯΄λ‹€.

Hook의 μ’…λ₯˜

βœ… useState

1
2
3
4
5
6
7
8
9
10
11
12
function Counter(props) {
    var count = 0;
    
    return (
    	<div>
            <p>총 {count}번 ν΄λ¦­ν–ˆμŠ΅λ‹ˆλ‹€.</p>
            <button onClick={() => count++}>
            	클릭
            </button>
        </div>
    );
}
  • μœ„ μ½”λ“œλŠ” λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ count 값을 증가 μ‹œν‚¬ μˆ˜λŠ” μžˆμ§€λ§Œ λ Œλ”λ§μ΄ λ‹€μ‹œ μΌμ–΄λ‚˜μ§€ μ•Šμ•„ κ°±μ‹  된 count 값이 화면에 ν‘œμ‹œλ˜μ§€ μ•ŠλŠ”λ‹€.
  • λ”°λΌμ„œ μ•„λž˜μ˜ μ½”λ“œμ™€ 같이 Stateλ₯Ό μ‚¬μš©ν•΄μ„œ 값이 λ°”λ€” λ•Œλ§ˆλ‹€ λ‹€μ‹œ λ Œλ”λ§ λ˜λ„λ‘ ν•΄μ•Ό ν•  ν•„μš”μ„±μ΄ μžˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { useState } from "react";

function Counter(props) {
    const [count, setCount] = useState(0);
    
    return (
    	<div>
            <p>총 {count}번 ν΄λ¦­ν–ˆμŠ΅λ‹ˆλ‹€.</p>
            <button onClick={() => setCount(count + 1)}>
            	클릭
            </button>
        </div>
    );
}
  • μœ„μ˜ Counter(props) λ©”μ„œλ“œλŠ” λ²„νŠΌμ΄ λˆŒλ Έμ„ λ•ŒΒ setCount()Β ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μ„œ countλ₯Ό 증가 μ‹œν‚¨λ‹€.
  • count의 값이 λ³€κ²½λ˜λ©΄ Componentκ°€ λ‹€μ‹œ λ Œλ”λ§λ˜λ©΄μ„œ 화면에 증가 된 count 값을 ν‘œμ‹œν•  수 μžˆλ‹€.
  • Class Componentμ—μ„œλŠ” setState() ν•¨μˆ˜ ν•˜λ‚˜λ₯Ό μ‚¬μš©ν•΄μ„œ λͺ¨λ“  State 값을 κ°±μ‹  ν•  수 μžˆμ—ˆμ§€λ§Œ Functional Componentμ—μ„œλŠ” λ³€μˆ˜ 각각에 λŒ€ν•΄ set ν•¨μˆ˜κ°€ λ”°λ‘œ μ‘΄μž¬ν•œλ‹€.

βœ… useEffect

1
useEffect(μ΄νŽ™νŠΈ ν•¨μˆ˜, μ˜μ‘΄μ„± λ°°μ—΄);
  • Side Effectλ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ 훅이닀.
  • Side Effect라고 ν•˜λ©΄ 뢀정적인 λŠλ‚Œμ„ κ°€μ§€κ³  μžˆμ§€λ§Œ Reactμ—μ„œ λ§ν•˜λŠ” Side EffectλŠ” μ„œλ²„μ—μ„œ 데이터λ₯Ό λ°›μ•„μ˜€κ±°λ‚˜ μˆ˜λ™μœΌλ‘œΒ DOM을 λ³€κ²½ν•˜λŠ” λ“±μ˜ 일반적인 μ΄νŽ™νŠΈλ₯Ό μ˜λ―Έν•œλ‹€.
  • Class Componentμ—μ„œ μ œκ³΅ν•˜λŠ” 생λͺ…μ£ΌκΈ° ν•¨μˆ˜μΈ componentDidMount(), componentDidUpdate(), componentWillUnmount()와 λ™μΌν•œ κΈ°λŠ₯을 ν•˜λ‚˜λ‘œ ν†΅ν•©ν•΄μ„œ μ œκ³΅ν•œλ‹€.
  • μ˜μ‘΄μ„± λ°°μ—΄ μ•ˆμ— μžˆλŠ” λ³€μˆ˜ 쀑에 ν•˜λ‚˜λΌλ„ 값이 λ³€κ²½λ˜μ—ˆμ„ λ•Œ μ΄νŽ™νŠΈ ν•¨μˆ˜κ°€ μ‹€ν–‰λœλ‹€.
  • 기본적으둜 μ΄νŽ™νŠΈ ν•¨μˆ˜λŠ” 처음 Componentκ°€ λ Œλ”λ§ 된 이후와 μ—…λ°μ΄νŠΈλ‘œ μΈν•œ μž¬λ Œλ”λ§ 이후에 μ‹€ν–‰λœλ‹€.
  • λ§Œμ•½ μ΄νŽ™νŠΈ ν•¨μˆ˜κ°€ Mount, Unmount μ‹œμ— 단 ν•œ 번만 μ‹€ν–‰λ˜κ²Œ ν•˜κ³  μ‹ΆμœΌλ©΄ μ˜μ‘΄μ„± 배열에 빈 배열을 λ„£μœΌλ©΄ λœλ‹€.
  • μ΄λ ‡κ²Œ ν•˜λ©΄ μ΄νŽ™νŠΈκ°€ propsλ‚˜ State에 μžˆλŠ” μ–΄λ–€ 값에도 μ˜μ‘΄ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ μ—¬λŸ¬ 번 μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€.
  • μ˜μ‘΄μ„± λ°°μ—΄ 없이 useEffect()λ₯Ό μ‚¬μš©ν•˜λ©΄ ReactλŠ”Β DOM이 λ³€κ²½λœ 이후에 ν•΄λ‹Ή μ΄νŽ™νŠΈ ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λΌλŠ” 의미둜 받아듀인닀.
  • κ·Έλž˜μ„œ Componentκ°€ 처음 λ Œλ”λ§ 될 λ•Œλ₯Ό ν¬ν•¨ν•΄μ„œ 맀번 λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ μ΄νŽ™νŠΈκ°€ μ‹€ν–‰λ˜λŠ”λ°, 결과적으둜 componentDidMount(), componentDidUpdate()와 λ™μΌν•œ 역할을 ν•˜κ²Œ λœλ‹€.
  • componentWillUnmount()λŠ” useEffect()μ—μ„œ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λŠ” Componentκ°€ Unmount될 λ•Œ ν˜ΈμΆœλœλ‹€.

βœ… useMemo

1
2
3
const memoizedValue = useMemo(() => {
	return ν•¨μˆ˜(μ˜μ‘΄μ„± λ³€μˆ˜1, μ˜μ‘΄μ„± λ³€μˆ˜2);
}, [μ˜μ‘΄μ„± λ³€μˆ˜1, μ˜μ‘΄μ„± λ³€μˆ˜2]);
  • Memoized valueλ₯Ό λ°˜ν™˜ν•˜λŠ” Hook이닀.
  • μ˜μ‘΄μ„± 배열에 λ“€μ–΄ μžˆλŠ” λ³€μˆ˜κ°€ λ³€ν–ˆμ„ κ²½μš°μ—λ§ŒΒ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μƒˆλ‘œμš΄ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λ©°, κ·Έλ ‡μ§€ μ•Šμ€ κ²½μš°λŠ” κΈ°μ‘΄ ν•¨μˆ˜μ˜ κ²°κ³Όλ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•œλ‹€.
  • Componentκ°€ λ‹€μ‹œ λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ 연산이 λ§Žμ€ μž‘μ—…μ˜ λ°˜λ³΅μ„ ν”Όν•  수 μžˆλ‹€.
  • λ Œλ”λ§μ΄ μΌμ–΄λ‚˜λŠ” λ™μ•ˆ μ‹€ν–‰ν•΄μ„œλŠ” μ•ˆ 될 μž‘μ—…μ„Β useMemo에 λ„£μœΌλ©΄ μ•ˆλœλ‹€λŠ” 점을 μœ μ˜ν•΄μ•Ό ν•œλ‹€.
  • μ˜μ‘΄μ„± 배열을 λ„£μ§€ μ•Šμ„ 경우 λ Œλ”λ§μ΄ 일어날 λ•Œλ§ˆλ‹€ ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λ©°, μ˜μ‘΄μ„± 배열에 빈 배열을 넣을 경우 Component Mount μ‹œμ—λ§Œ ν•¨μˆ˜κ°€ μ‹€ν–‰λœλ‹€.

βœ… useCallback

  • useMemo와 μœ μ‚¬ν•˜μ§€λ§Œ ν•œ κ°€μ§€ 차이점은 값이 μ•„λ‹Œ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•œλ‹€.Β 
  • useCallbackμ—μ„œ νŒŒλΌλ―Έν„°λ‘œ λ°›λŠ” 이 ν•¨μˆ˜λ₯Ό Callback이라고 λΆ€λ₯Έλ‹€.
  • μ˜μ‘΄μ„± 배열에 따라 Memoized valueλ₯Ό λ°˜ν™˜ν•œλ‹€λŠ” μ μ—μ„œλŠ” useMemo와 μ™„μ „νžˆ λ™μΌν•˜λ‹€.
  • λ§Œμ•½Β useCallback을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  Component 내에 ν•¨μˆ˜λ₯Ό μ •μ˜ν•œλ‹€λ©΄ 맀번 λ Œλ”λ§μ΄ 일어날 λ•Œλ§ˆλ‹€ ν•¨μˆ˜κ°€ μƒˆλ‘œ μ •μ˜λœλ‹€.
  • λ”°λΌμ„œ ν•΄λ‹Ή Hook을 μ‚¬μš©ν•˜μ—¬ νŠΉμ • λ³€μˆ˜μ˜ 값이 λ³€ν•œ κ²½μš°μ—λ§Œ ν•¨μˆ˜λ₯Ό λ‹€μ‹œ μ •μ˜ν•˜μ—¬ λ°˜λ³΅μ„ μ—†μ• μ£ΌλŠ” 것이 μ˜¬λ°”λ₯΄λ‹€.

βœ… useRef

1
const refContainer = useRef(μ΄ˆκΉƒκ°’);
  • Referenceλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•œ Hook으둜, Reference 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
  • Reactμ—μ„œ Referenceλž€ νŠΉμ • Component에 μ ‘κ·Όν•  수 μžˆλŠ” 객체λ₯Ό μ˜λ―Έν•œλ‹€.
  • Reference κ°μ²΄μ—λŠ” currentλΌλŠ” 속성이 μžˆλŠ”λ° μ΄λŠ” ν˜„μž¬ μ°Έμ‘°ν•˜κ³  μžˆλŠ” Elementλ₯Ό μ˜λ―Έν•œλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function TextInputWithFocusButton(props) {
    const inputElem = useRef(null);
    
    const onButtonClick = () => {
    	inputElem.current.focus(); 	
    };
    
    return (
    	<div>
            <input ref={inputElem} type="text"/>
            <button onClick={onButtonClick}>Focus the input</button>
        </div>
    );
}
  • μœ„ μ½”λ“œλŠ” λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄Β inputΒ νƒœκ·Έλ₯Ό Focusingν•˜λŠ” μ˜ˆμ œμ΄λ‹€.
  • 맀번 λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ 항상 같은 Reference 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
  • μ£Όμ˜ν•΄μ•Ό ν•  점은 useRef 훅은 λ‚΄λΆ€μ˜Β current 속성이 λ³€κ²½λ˜λ”λΌλ„ λ‹€μ‹œ λ Œλ”λ§ ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것이닀.
  • λ”°λΌμ„œΒ Reference에 DOM nodeκ°€ μ—°κ²°λ˜κ±°λ‚˜ 뢄리될 경우 μ–΄λ–€ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κ³  μ‹Άλ‹€λ©΄Β callbackref 방식을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
  • μ΄λŠ”Β DOM node의 ref 속성에 Reference 객체 λŒ€μ‹ Β useCallbackΒ λ°˜ν™˜ ν•¨μˆ˜λ₯Ό λ„£μ–΄μ£ΌλŠ” 것이닀.
  • μ΄λ ‡κ²Œ 되면 μžμ‹ Componentκ°€ λ³€κ²½λ˜μ—ˆμ„ λ•Œ μ•Œλ¦Όμ„ 받을 수 있고, 이λ₯Ό 톡해 λ‹€λ₯Έ 정보듀을 Update ν•  수 μžˆλ‹€.Β 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function MeasureExample(props) {
	const [height, setHeight] = useState(0);
    
    const measuredRef = useCallback(node => {
    	if (node !== null) {
        	setHeight(node.getBoundingClientRect().height);
        }
    }, []);
    
    return (
    	<div>
        	<h1 ref={measureRef}>μ•ˆλ…•, λ¦¬μ•‘νŠΈ</h1>
            <h2>μœ„ ν—€λ”μ˜ λ†’μ΄λŠ” {Math.round(height)}pxμž…λ‹ˆλ‹€.</h2>
        </div>
    );
}
  • μœ„μ˜ μ˜ˆμ œμ—μ„œλŠ”Β h1Β νƒœκ·Έμ˜ 높이λ₯Ό Update ν•˜κ³  μžˆλ‹€.Β 
  • useCallback의 μ˜μ‘΄μ„± λ°°μ—΄λ‘œ 빈 배열이 λ“€μ–΄κ°€ μžˆμœΌλ―€λ‘œ Mount, Unmount μ‹œμ—λ§Œ Callback ν•¨μˆ˜κ°€ ν˜ΈμΆœλœλ‹€.Β 

Hook의 κ·œμΉ™

βœ… Hook은 μ΅œμƒμœ„ λ ˆλ²¨μ—μ„œλ§Œ ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.

  • λ°˜λ³΅λ¬Έμ΄λ‚˜ 쑰건문 λ˜λŠ” μ€‘μ²©λœ ν•¨μˆ˜ μ•ˆμ΄ μ•„λ‹Œ React Functional Component의 μ΅œμƒμœ„ λ ˆλ²¨μ—μ„œ Hook을 ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.
  • 이 κ·œμΉ™μ— 따라 Hook은 Componentκ°€ λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ 맀번 같은 μˆœμ„œλ‘œ ν˜ΈμΆœλ˜μ–΄μ•Ό ν•œλ‹€.

βœ… React Functional Componentμ—μ„œ Hook을 ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.

  • 일반 Javascript ν•¨μˆ˜μ—μ„œ Hook을 ν˜ΈμΆœν•˜λ©΄ μ•ˆ λœλ‹€.
  • React Functional Componentμ—μ„œ ν˜ΈμΆœν•˜κ±°λ‚˜ 직접 λ§Œλ“  Custom Hookμ—μ„œ ν˜ΈμΆœν•  수 μžˆλ‹€.

Custom Hook

  • μ—¬λŸ¬ Componentμ—μ„œ 반볡적으둜 μ‚¬μš©λ˜λŠ” λ‘œμ§μ„ Hook으둜 λ§Œλ“€μ–΄ μž¬μ‚¬μš©ν•˜κΈ° μœ„ν•΄ Custom Hook을 λ§Œλ“ λ‹€.
  • νŒŒλΌλ―Έν„°λ‘œ 무엇을 받을지, μ–΄λ–€ 것을 λ°˜ν™˜ν• μ§€ κ°œλ°œμžκ°€ 직접 μ •ν•  수 μžˆλ‹€.Β 
  • Component λͺ…은 κΌ­ use둜 μ‹œμž‘ν•˜λ„λ‘ ν•˜μ—¬ ν•΄λ‹Ή Componentμ—μ„œ Hook을 ν˜ΈμΆœν•œλ‹€λŠ” 것을 λͺ…μ‹œν•΄μ•Ό ν•œλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function UserStatus(props) {
    const [isOnline, setIsOnline] = useState(null);
    
    useEffect(() => {
    	function handleStatusChange(status) {
            setIsOnline(status.isOnline);
        }
        
	    ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
	    return () => {
    	    ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });

    if (isOnline === null) {
    	return 'λŒ€κΈ°μ€‘...';
    }
    return isOnline ? '온라인' : 'μ˜€ν”„λΌμΈ';
}
  • 상기 μ½”λ“œμ— Custom Hook을 μ μš©ν•˜κ³ μž ν•œλ‹€.Β 
  • isOnlineμ΄λΌλŠ” State에 따라 μ‚¬μš©μžμ˜ 온라인 μ—¬λΆ€λ₯Ό ν…μŠ€νŠΈλ‘œ λ³΄μ—¬μ£ΌλŠ” Component이닀.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function useUserStatus(userId) {
    const [isOnline, setIsOnline] = useState(null);
    
    useEffect(() => {
    	function handleStatusChange(status) {
        	setIsOnline(status.isOnline);
        }
        
    ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
	    return () => {
    	    ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        };
    });

    return isOnline;
}
  • State와 κ΄€λ ¨λœ 쀑볡 λ‘œμ§μ„Β useUserStatusλΌλŠ” Costom Hook으둜 μΆ”μΆœν•΄λ‚Έ 것이닀.
  • 이제 UserStatus와 UserListItemμ—μ„œ Custom Hook을 μ μš©ν•˜λ©΄ λœλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// UserStatus.jsx
function UserStatus(props) {
    const isOnline = useUserStatus(props.user.id);
    
    if (isOnline === null) {
    	return 'λŒ€κΈ°μ€‘...';
    }
    return isOnline ? '온라인' : 'μ˜€ν”„λΌμΈ';
}

// UserListItem.jsx
function UserListItem(props) {
	const isOnline = useUserStatus(props.user.id);
	
	return (
		<li style=>
			{props.user.name}
		</li>
	);
}
  • μœ„μ²˜λŸΌ 같은 Custom Hook을 μ‚¬μš©ν•˜λŠ” 두 개의 Componentκ°€ Stateλ₯Ό κ³΅μœ ν•˜λŠ” 것은 μ•„λ‹ˆλ‹€.
  • λ‹¨μˆœνžˆΒ StateΒ μ—°κ΄€ λ‘œμ§μ„ μž¬μ‚¬μš©μ΄ κ°€λŠ₯ν•˜κ²Œ λ§Œλ“  것 뿐이닀.
  • μ—¬λŸ¬ 개의 Componentμ—μ„œ ν•˜λ‚˜μ˜ Custom Hook을 μ‚¬μš©ν•˜λ”λΌλ„ Component λ‚΄λΆ€μ˜ Stateλ‚˜ effectsλŠ” μ „λΆ€ λΆ„λ¦¬λ˜μ–΄ μžˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const userList = [
    { id : 1, name : 'Inje' },
    { id : 2, name : 'Mike' },
    { id : 3, name : 'Steve' }
];

function ChatUserSelector(props) {
    const [userId, setUserId] = userState(1);
    const isUserOnline = useUserStatus(userId);
	    
    return (
	    <div>
		    <Circle color={isUserOnline ? 'green' : 'red'}/>
		    <select
			    value={userId}
			    onChange={event => setUserId(Number(event.target.value))}>
	            {userList.map(user => (
	                <option key={user.id} value={user.id}>
	                    {user.name}
	                </option>
	            ))}
	        </select>
	    </div>
    );
}
  • Hook κ°„μ˜ 데이터λ₯Ό κ³΅μœ ν•˜λŠ” 예제 μ½”λ“œμ΄λ‹€.
  • userIdκ°€ 변경될 λ•Œλ§ˆλ‹€ setUserId() ν•¨μˆ˜κ°€ 호좜되고, useUserStatus Hook은 이전에 μ„ νƒλœ μ‚¬μš©μžλ₯Ό ꡬ독 μ·¨μ†Œν•˜κ³  μƒˆλ‘œ μ„ νƒλœ μ‚¬μš©μžμ˜ 온라인 μ—¬λΆ€λ₯Ό κ΅¬λ…ν•œλ‹€.

μ‹€μŠ΅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import React, { useEffect, useState } from "react";

const MAX_CAPACITY = 10;
const buttonStyle = {
	padding: "8px 16px",
	marginRight: "8px",
	backgroundColor: "#4CAF50",
	color: "white",
	border: "none",
	borderRadius: "4px",
	cursor: "pointer",
	fontSize: "14px",
};

const disabledButtonStyle = {
	...buttonStyle,
	backgroundColor: "#ccc",
	cursor: "not-allowed",
};

function UseCounter(initialValue) {
	const [count, setCount] = useState(initialValue);
	const increaseCount = () => setCount((count) => count + 1);
	const decreaseCount = () => setCount((count) => Math.max(count - 1, 0));
	
	return [count, increaseCount, decreaseCount];
}

function ManageTeamMembers(props) {
	const [isFull, setIsFull] = useState(false);
	const [count , increaseCount, decreaseCount] = UseCounter(0)
	
	useEffect(() => {
		console.log("useEffect() λ©”μ†Œλ“œκ°€ ν˜ΈμΆœλ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
		console.log(`정원 도달여뢀 ${isFull}`);
	});
	
	useEffect(() => {
		setIsFull(count >= MAX_CAPACITY);
		console.log(`졜근 개수: ${count}`);
	}, [count]);
	
	return (
		<div style=>
			<p>{`νŒ€μ— κ°€μž…ν•œ λ©€λ²„λŠ” 총 ${count}λͺ… μž…λ‹ˆλ‹€.`}</p>
			<button onClick={increaseCount} style={isFull ? disabledButtonStyle : buttonStyle} disabled={isFull}>κ°€μž…</button>
			<button onClick={decreaseCount} style={buttonStyle}>νƒˆν‡΄</button>
			
			{isFull && <p style=>정원이 κ°€λ“μ°ΌμŠ΅λ‹ˆλ‹€.</p>}
		</div>
	);
}

export default ManageTeamMembers;
  • useEffect()λ₯Ό μ„ μ–Έν•˜μ—¬ Team Componentκ°€ λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ useEffect() λ©”μ„œλ“œμ˜ 호좜 여뢀와 νŒ€μ˜ 멀버 정원 도달 μ—¬λΆ€λ₯Ό μ½˜μ†” λ‘œκ·Έμ— μ°λŠ”λ‹€.
  • count μƒνƒœκ°€ λ³€ν•  λ•Œλ§ˆλ‹€ 졜근 개수λ₯Ό μ½˜μ†” λ‘œκ·Έμ— μ°λŠ”λ‹€.
  • κ°€μž… λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ λ©€λ²„μ˜ count μˆ˜κ°€ μ¦κ°€ν•˜λ©°, 정원이 꽉 찼을 경우 λΉ„ν™œμ„±ν™”λœλ‹€.
  • νƒˆν‡΄ λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ λ©€λ²„μ˜ count μˆ˜κ°€ κ°μ†Œν•œλ‹€.
  • λ˜ν•œ 정원이 꽉 μ°° 경우 λΉ¨κ°„ κΈ€μ”¨λ‘œ β€œμ •μ›μ΄ 가득 μ°ΌμŠ΅λ‹ˆλ‹€.” 문ꡬ가 λ…ΈμΆœλœλ‹€.

회고

  • Hook은 ꡉμž₯히 μ€‘μš”ν•˜κ³ λ„ λ³΅μž‘ν•œ κΈ°λŠ₯μ΄μ–΄μ„œ 사싀 μ™„λ²½νžˆ μˆ™μ§€ν•˜μ§€λŠ” λͺ»ν–ˆλ‹€.
  • λ°˜λ³΅ν•΄κ°€λ©° λΆ€μ‘±ν•œ 뢀뢄은 곡뢀 ν•΄μ•Όκ² λ‹€λŠ” 생각이 λ“€μ—ˆλ‹€.
This post is licensed under CC BY 4.0 by the author.