Skip to content

SeonHyungJo/react-hook-sample

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

28 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

react-hook-sample

Contents

Basic Hooks

1. useState

const [state, setState] = useState(initialState);

์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ ์ดˆ๊ธฐ๊ฐ’ ์„ ๋„ฃ์–ด์ค€๋‹ค. useState ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋˜ state ์ดˆ๊ธฐํ™” ์ž‘์—…๊ณผ ๋™์ผํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์‰ฝ๋‹ค. ์ƒ์„ฑ์‹œ ์šฐ๋ฆฌ๋Š” ๋ฐฐ์—ด์„ ๋ฐ›์•„ ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋“  Hook์€ 2๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ›์•„์˜จ๋‹ค.(๋“œ๋ฌผ๊ฒŒ ์•„๋‹Œ ๊ฒƒ๋„ ์žˆ๋‹ค.)

๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋„˜๊ฒจ์ฃผ์—ˆ๋˜ ์ดˆ๊ธฐํ™” ๊ฐ’์ด ๋“ค์–ด์˜ค๊ณ  ์ดํ›„์—๋Š” ๋ณ€๊ฒฝ๋œ ๊ฐ’์ด ๋„˜์–ด์˜ค๊ฒŒ ๋œ๋‹ค. ๋‘๋ฒˆ์งธ๋Š” ๊ฐ’๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜๋‹ค.

re-render๊ฐ€ ๋  ๊ฒฝ์šฐ useState์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ ์ฒซ ๋ฒˆ์งธ ๊ฐ’์€ ํ•ญ์ƒ ์—…๋ฐ์ดํŠธ๋ฅผ ์ ์šฉํ•œ ํ›„ ๊ฐ€์žฅ ์ตœ๊ทผ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.


1.1 Functional updates

์—ญ์‹œ๋‚˜ ์šฐ๋ฆฌ๋Š” ์ธ์ž๋กœ ํ•จ์ˆ˜๋ฅผ ๋ณด๋‚ผ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ธฐ์กด์— ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋˜ setState ๋ฉ”์†Œ๋“œ์™€๋Š” ๋‹ฌ๋ผ์„œ ์ž๋™์œผ๋กœ ๋ณ‘ํ•ฉ์„ ์‹œ์ผœ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

์ฆ‰ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค๋•Œ ๋งˆ๋‹ค ํ•„์š”์— ๋”ฐ๋ผ ๋ณ‘ํ•ฉ์„ ํ•ด์ค˜์•ผํ•œ๋‹ค.

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues}; // ๊ฐ„๋‹จํ•˜๊ฒŒ spread๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒˆ๋กœ ์ƒ์„ฑ
});

1.2 Lazy initial state

initial state ์— ์—ญ์‹œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฆฌ์•กํŠธ ์‚ฌ์ดํŠธ์—์„œ ํ‘œํ˜„์œผ๋กœ๋Š” ๊ฐ’ ๋น„์‹ผ ๊ณ„์‚ฐ ์ด๋ผ๋ฉด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ‘œํ˜„ํ•˜๋ผ๊ณ  ํ•œ๋‹ค.

const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

1.3 Bailing out of a state update

๊ฐ™์€ ๊ฐ’์„ ๋‹ค์‹œ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋”๋ผ๋„ ๋ฆฌ์•กํŠธ์—์„œ๋Š” ์ž์‹์„ re-render ํ•˜๊ฑฐ๋‚˜ effect ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.(Object.is๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋น„๊ตํ–ˆ๋‹ค๊ณ  ํ•จ_์ฝ์œผ๋ฉด ์œ ์šฉํ•จ)


2. useEffect()

useEffect(() => {
  // Update the document title using the browser API
  document.title = `You clicked ${count} times`;
});

๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋œ ํ›„์— ์‹คํ–‰์ด ๋œ๋‹ค.

์–ด๋–ค value ๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„๋•Œ ์‹คํ–‰๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.(๋‚ด๊ฐ€ ๋ฐ”๋ผ๋ณด๊ณ  ์‹ถ์€ ์ธ์ž๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.)


2.1 Cleaning up an effect

ํ™”๋ฉด์„ ๋– ๋‚˜๊ธฐ ์ „์— ์ •๋ฆฌ๋ฅผ ํ• ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.(dispose()์™€ ๊ฐ™์€ ๋А๋‚Œ์ž„)

์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด๊ฒŒ ๋˜๋ฉด return์œผ๋กœ ๋งŒ๋“  ํ•จ์ˆ˜๊ฐ€ ์ •๋ฆฌ๋ฅผ ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // Clean up the subscription
    subscription.unsubscribe();
  };
});

๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ์„ ๋ฐฉ์ง€ํ•˜ํ•˜๊ธฐ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ UI๋กœ ๋ถ€ํ„ฐ ์ œ๊ฑฐ๋˜๊ธฐ ์ „์— ์‹คํ–‰ํ•œ๋‹ค.

๋งŒ์•ฝ์— ๊ตฌ๋…์„ ์ทจ์†Œํ•˜๊ธฐ์ „์— ๋‹ค๋ฅธ effect๊ฐ€ ์‹คํ–‰์ด ๋˜์–ด ๊ตฌ๋…์„ ํ•œ๋‹ค๋ฉด? ์ด๋Ÿฌํ•œ ์ผ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๊ณ  ์‹ถ๋‹ค๋ฉด?


2.2 Timing of effects

componentDidMount ๋‚˜ componentDidUpdate ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ layout๊ณผ paint ๊ฐ€ ๋๋‚˜๊ณ  ๋‚˜์„œ useEffect๊ฐ€ ์‹คํ–‰์ด๋œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋‹ˆ ๋งŒ๋“  ๊ณตํ†ต์˜ ๋ถ€์ž‘์šฉ์— ์žˆ์–ด์„œ ์ ํ•ฉํ•˜๋‹ค ๋ผ๊ณ  ํ•˜๋Š”๋ฐ, ํ™”๋ฉด์—์„œ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๊ฒƒ์ด ๋ฉˆ์ถ”๋Š” ํ˜„์ƒ์ด ์ผ์–ด๋‚˜์ง€ ์•Š์œผ๋‹ˆ๊นŒ ๊ทธ๋Ÿฐ ๊ฒƒ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜์žˆ๋Š” DOM ๋ณ€์ด๋Š” ์‹œ๊ฐ์ ์ธ ๋ถˆ์ผ์น˜๋ฅผ ์ธ์‹ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋‹ค์Œ ํŽ˜์ธํŠธ ์ „์— ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

useLayoutEffect ๋Š” useEffect ๋™์ผํ•œ ๊ธฐ๋Šฅ์ด์ง€๋งŒ ์‹คํ–‰๋˜๋Š” ์‹œ์ ์ด ๋‹ค๋ฅธ Hook ์ด๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•จ๋ฉด ์‹คํ–‰๋˜๋Š” ์‹œ์ ์ด ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์ธ๋ฐ useEffect ๋Š” ์•„๋ž˜์— ์ง„ํ•œ ๊ธ€์”จ์™€ ๊ฐ™์ด ์™„์ „ํžˆ ํ™”๋ฉด์ด ๊ทธ๋ ค์กŒ๋‹ค ๋ผ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์ง€๋งŒ useLayoutEffect๋Š” ์‹œ์ ์ด Dom์˜ ๋ณ€ํ™”๋Š” ์žˆ์ง€๋งŒ repaint, reflow๊ฐ€ ๋˜์ง€ ์•Š์€ ์‹œ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

useEffect๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ paintํ• ๋•Œ ๊นŒ์ง€ ์—ฐ๊ธฐ๋ฅผ ํ•˜์ง€๋งŒ ์ƒˆ๋กœ์šด ๋ Œ๋”๋ง์ „์— ์‹œ์ž‘๋  ๊ฒƒ์ด ๋ณด์ฆํ•œ๋‹ค.


2.3 Conditionally firing an effect

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

useEffect ์—๋Š” 2๋ฒˆ์งธ ์ธ์ž๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์—ฌ๊ธฐ์— ๋“ค์–ด๊ฐ€๋Š” ๋ฐฐ์—ด์€ ๋‚ด๊ฐ€ ๋ฐ”๋ผ๋ณผ ๊ฒƒ ์œผ๋กœ ์—ฌ๊ธฐ์„œ๋Š” props.source ์˜ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚ฌ์„ ๊ฒฝ์šฐ์—๋งŒ ์ž‘๋™ํ•˜๊ฒŒ ๋œ๋‹ค.

๋งŒ์•ฝ์— ์ธ์ž์— ์•„๋ฌด๊ฒƒ๋„ ์—†๋‹ค๋ฉด ๋งˆ์šดํŠธ์—์„œ ์‹คํ–‰๋˜๊ณ  ๋งˆ์šดํŠธ ํ•ด์ œ์—์„œ๋Š” ์ •๋ฆฌํ•œ๋‹ค.


3. useContext()

    const context = useContext(Context);

react@16.3๋ถ€ํ„ฐ ์ง€์›์„ ํ•œ Context ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. context object ๋ฅผ ๋ฐ›์•„์„œ ํ˜„์žฌ context ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

provider๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋ฉด Hooks์ด ์‹คํ–‰๋˜์–ด ์ตœ์‹ ์˜ ๊ฐ’์œผ๋กœ ๋‹น์—ฐํžˆ ๋™๊ธฐํ™”๊ฐ€ ๋œ๋‹ค.


Additional Hooks

4. useReducer

์šฐ๋ฆฌ๊ฐ€ ๋ฆฌ๋•์Šค์—์„œ ๋งŽ์ด ๋ณด๋˜ Reducer ์™€ ๋น„์Šทํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ๊ทธ๋ ‡๋‹ค๊ณ  ํ•œ๋‹ค.

    const initialState = {count: 0};
    
    // ์šฐ๋ฆฌ๊ฐ€ Redux์—์„œ ๋งŒ๋“ค๋˜ Reducer ๋ถ€๋ถ„
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        default:
          throw new Error();
      }
    }
    
    function Counter({initialCount}) {
      // ์ดˆ๊ธฐํ™” ๊ฐ’๊ณผ Reducer๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.
      const [state, dispatch] = useReducer(reducer, initialState);

      return (
        <>
          Count: {state.count}
          <button onClick={() => dispatch({type: 'increment'})}>+</button>
          <button onClick={() => dispatch({type: 'decrement'})}>-</button>
        </>
      );
    }

4.1 Specifying the initial state

2๋ฒˆ์งธ ์ธ์ž๋กœ ์ดˆ๊ธฐํ™” state ๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.(๊ฐ„๋‹จํ•˜๊ฒŒ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•)

    const [state, dispatch] = useReducer(
        reducer,
        {count: initialCount}
      );

4.2 Lazy initialization

๋งŒ์•ฝ ๋А์Šจํ•˜๊ฒŒ ์ดˆ๊ธฐ state ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด 3๋ฒˆ์งธ ์ธ์ž๋กœ init function ์„ ๋„˜๊ธฐ์ž

๊ทธ๋Ÿฌ๋ฉด init(initialArg) ์ด๋Ÿฐ์‹์œผ๋กœ ํ˜ธ์ถœ์ด ๋  ๊ฒƒ์ด๋‹ค.

    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: 'increment'})}>+</button>
          <button onClick={() => dispatch({type: 'decrement'})}>-</button>
        </>
      );
    }

4.3 Bailing out of a dispatch

useState ์™€ ๋™์ผํ•˜๊ฒŒ ๊ฐ™์€ ๊ฐ’์„ ๋„˜๊ธฐ๊ฒŒ ๋˜๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ ๋น„๊ต๋ฅผ ํ•ด์„œ ์ž์‹ ๋ Œ๋”๋ง๊ณผ effect๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค.


5. useCallback

    const memoizedCallback = useCallback(
      () => {
        doSomething(a, b);
      },
      [a, b],
    );

Returns a memoized callback.

์ธ๋ผ์ธ ์ฝœ๋ฐฑ๊ณผ ์ž…๋ ฅ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. useCallback ์€ ์ž…๋ ฅ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์—๋งŒ ๋ณ€๊ฒฝ๋˜๋Š” ์ฝœ๋ฐฑ์˜ memoized ๋ฒ„์ „์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค

์ฆ‰ a ๋˜๋Š” b ๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜์—ˆ๋‹ค๋ฉด ํ•จ์ˆ˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • ๋™์ผํ•œ ํ‘œํ˜„
    useCallback(fn, inputs) //is equivalent to 
    useMemo(() => fn, inputs).

6. useMemo

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Returns a memoized value.

๋ Œ๋”๋ง๋˜๋Š” ๋™์•ˆ ์— useMemo์— ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰์ด ๋œ๋‹ค.

์ฆ‰, ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์žˆ์–ด์„œ ์กฐ์‹ฌํ•ด์•ผํ•œ๋‹ค. ๋ Œ๋”๋ง๋™์•ˆ ํ•˜์ง€์•Š๋Š” ๊ฒƒ์„ ํ•˜์ง€ ์•Š์•„์•ผํ•œ๋‹ค. side effect๋ฅผ ์œ„ํ•ด useEffect๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

useEffect ์™€ ๋™์ผํ•˜๊ฒŒ ๋ฐฐ์—ด์ด ๋„˜์–ด๊ฐ€์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋งค์ˆœ๊ฐ„ ์ฒซ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํƒ€๊ฒŒ ๋œ๋‹ค.

์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด์„œ useMemo๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ์ƒ๊ฐ์ด ๋œ๋‹ค.


7. useRef

    function TextInputWithFocusButton() {
      const inputEl = useRef(null);
      const onButtonClick = () => {
        // `current` points to the mounted text input element
        inputEl.current.focus();
      };

      return (
        <>
          <input ref={inputEl} type="text" />
          <button onClick={onButtonClick}>Focus the input</button>
        </>);
    }

8. useImperativeHandle

    useImperativeHandle(ref, createHandle, [inputs])

useImperativeHandle ์€ ref ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋ถ€๋ชจ ๊ตฌ์„ฑ ์š”์†Œ์— ๋…ธ์ถœ๋˜๋Š” ์ธ์Šคํ„ด์Šค ๊ฐ’์„ ์‚ฌ์šฉ์ž ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

    function FancyInput(props, ref) {
      const inputRef = useRef();

      useImperativeHandle(ref, () => ({
        focus: () => {
          inputRef.current.focus();
        }
      }));

      return <input ref={inputRef} ... />;
    }
    FancyInput = forwardRef(FancyInput);

9. useLayoutEffect

์„œ๋ช…์€ useEffect์™€ ๋™์ผํ•˜์ง€๋งŒ ๋ชจ๋“  DOM ๋ณ€์ด ํ›„์— ๋™๊ธฐ์ ์œผ๋กœ ์‹œ์ž‘ ๋ฉ๋‹ˆ๋‹ค.

useLayoutEffect ๋‚ด๋ถ€์—์„œ ์˜ˆ์•ฝ๋œ ์—…๋ฐ์ดํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํŽ˜์ธํŠธํ•  ์ˆ˜ ์žˆ๊ธฐ ์ „์— ๋™๊ธฐ์ ์œผ๋กœ ํ”Œ๋Ÿฌ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜์—ฌ DOM์—์„œ ๋ ˆ์ด์•„์›ƒ์„ ์ฝ๊ณ  ๋™๊ธฐ์ ์œผ๋กœ ๋‹ค์‹œ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐ์ ์ธ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ง‰์ง€ ์•Š๋„๋ก useEffect๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•จ


10. useDebugValue

useDebugValue๋Š” React DevTools์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ ํ›„ํฌ ๋ ˆ์ด๋ธ”์„ ํ‘œ์‹œํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
    
      // ...
    
      // Show a label in DevTools next to this Hook
      // e.g. "FriendStatus: Online"
      useDebugValue(isOnline ? 'Online' : 'Offline');
    
      return isOnline;
    }

10.1 Defer formatting debug values

    useDebugValue(date, date => date.toDateString());

Reference

-usehooks

About

This is place to study react-hook. Let's create custom hooks

Topics

Resources

License

Stars

4 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors