ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React :: Hook, useState, useEffect, ์‚ฌ์šฉ์ž ์ •์˜ Hook
    PROGRAMMING/React 2021. 3. 31. 13:09

    Hook

    Hook์€ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ React state์™€ ์ƒ๋ช…์ฃผ๊ธฐ ๊ธฐ๋Šฅ(lifecycle features)์„ “์—ฐ๋™(hook into)“ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งํ•œ๋‹ค.

    useState, useEffect ์™€ ๊ฐ™์€ ๋‚ด์žฅ Hook ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์ง์ ‘ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

     

    Hook ์‚ฌ์šฉ ๊ทœ์น™

    Hook์€ ๊ทธ๋ƒฅ JavaScript ํ•จ์ˆ˜์ด์ง€๋งŒ, ๋‘ ๊ฐ€์ง€ ๊ทœ์น™์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•œ๋‹ค.

    • **์ตœ์ƒ์œ„(at the top level)**์—์„œ๋งŒ Hook์„ ํ˜ธ์ถœ! ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ์‹คํ–‰ํ•˜๋ฉด ์•ˆ๋จ
    • React ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ๋งŒ Hook์„ ํ˜ธ์ถœ! (๋‹น์—ฐํžˆ, Class ์•ˆ์—์„œ๋Š” Hook ์€ ๋™์ž‘ํ•˜์ง€ ์•Š์Œ) ์ผ๋ฐ˜ JavaScript ํ•จ์ˆ˜์—์„œ๋Š” Hook์„ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ๋จ

    ๊ทธ๋Ÿผ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๋Œ€ํ‘œ์ ์ธ ๋‚ด์žฅ Hook ๋‘ ๊ฐœ๋ฅผ ์‚ดํŽด๋ณด์ž.


    useState

    useState ๋Š” ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” state ์˜ ๊ฐœ๋…์„ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    ๋จผ์ €, ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์˜ ํ˜•ํƒœ๋ฅผ ์งš๊ณ  ๋„˜์–ด๊ฐ€๋ณด์ž.

     

    ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” ํฌ๊ฒŒ ๋‹ค์Œ์˜ ๋‘ ํ˜•ํƒœ๋กœ ์กด์žฌํ•œ๋‹ค.

    function Example(props) {
      // ์—ฌ๊ธฐ์„œ Hook์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
      return <div />;
    }
    const Example = (props) => {
      // ์—ฌ๊ธฐ์„œ Hook์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
      return <div />;
    }

     

    ๊ทธ๋ฆฌ๊ณ , ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ state ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.

    class Example extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0
        };
      }
      render() {
      	...
      }
    }

     

    ์ด์ „์— Props, State ๋ฅผ ๋ฐฐ์šธ ๋•Œ State ๋Š” ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ–ˆ๋‹ค.

    ๊ทธ๋Ÿผ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” State ์˜ ๊ฐœ๋…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š”๊ฐ€์— ๋Œ€ํ•œ ์˜๋ฌธ์„ ๊ฐ€์กŒ์—ˆ๋Š”๋ฐ, 

    useState ๋ฅผ ์‚ฌ์šฉํ•ด์„œ State ์˜ ๊ฐœ๋…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

     

     

    useState ์‚ฌ์šฉ ํ๋ฆ„ (์š”์•ฝ)

    useState ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ํฌ๊ฒŒ ๋‹ค์Œ์˜ ์„ธ ๋‹จ๊ณ„๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

     

    1) useState ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด,  useState Hook ๋ฅผ React ์—์„œ ๊ฐ€์ ธ์˜จ๋‹ค.

      import React, { useState } from 'react';

    2) useState ๋กœ state ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

    const [count, setCount] = useState(0);

    (์—ฌ๊ธฐ์„œ ๋Œ€๊ด„ํ˜ธ๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์€ "๋ฐฐ์—ด ๊ตฌ์กฐ ๋ถ„ํ•ด"๋ผ๋Š” JavaScript ๋ฌธ๋ฒ•์ด๋‹ค)

     

    3) useState ๊ฐ€ ๋งŒ๋“ค์–ด์ค€ state ๋ฅผ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋กœ state ๋ณ€์ˆ˜๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค.

    React ๋Š” ๋ณ€ํ™”๋ฅผ ์ธ์ง€ํ•˜๊ณ , ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•œ๋‹ค.

    import React, { useState } from 'react'; 2:
      function Example() {
        const [count, setCount] = useState(0); 5:
        return (
          <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>10:         Click me
            </button>
          </div>
        );
      }

     

    useState Hook ์„ ์‚ฌ์šฉํ•˜๋Š” ํ๋ฆ„์„ ์‚ดํŽด๋ดค๋‹ค.

    ๊ทธ๋Ÿฌ๋ฉด, useState ์— ์ธ์ž๋กœ ๋„˜๊ฒจ์ค€ ๊ฒƒ์€ ๋ฌด์—‡์œผ๋กœ ๋ฐ›์€ ๊ฒƒ์€ ๋ฌด์—‡์ผ๊นŒ?

    ๋จธ๋ฆฟ์†์— useState ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ๋ฆ„์„ ๊ทธ๋ ค๋‘๊ณ , ๋” ์„ธ๋ถ€์ ์œผ๋กœ ์‚ดํŽด๋ณด์ž.

     

    useState ์„ธ๋ถ€ ์‚ฌํ•ญ

    useState Hook ์„ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

    (ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š” this ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ useState ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์‚ฌ์šฉ)

      const [fruit, setFruit] = useState('apple');

    ์ด๊ฑด ๋ฌด์—‡์„ ์˜๋ฏธํ• ๊นŒ?

     

    ๋จผ์ € useState ์˜ ์ธ์ž๋กœ ๋„˜๊ฒจ์ค€ 'apple' ์€ fruit state ์˜ ์ดˆ๊ธฐ๊ฐ’์ด๋‹ค. 

    ๊ทธ๋ฆฌ๊ณ  useState ๋Š” 'apple' ์„ ์ดˆ๊ธฐ๊ฐ’์œผ๋กœ ๊ฐ€์ง€๋Š” fruit state ์™€ fruit ์˜ ๊ฐ’์„ ๊ฐฑ์‹ ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” setFruit ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

     

    ์ฆ‰, useState ๋ฅผ ํ†ตํ•ด ์ € ๋‘ ๊ฐ’์„ ๋ฐ›์•„์™”๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    //state ๊ฐ’ ๋ณ€๊ฒฝํ•˜๊ธฐ
    setFruit('banana')
    
    //state ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
     <p>You're fruit is {fruit} !</p>

    ์ด๋Ÿฌ๋ฉด fruit state ๊ฐ’์€ 'apple' ์ด ์•„๋‹Œ 'banana' ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

     

    ์ด๊ฒŒ ๋งŒ์ผ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜€๋‹ค๋ฉด, this.state.fruit ๋กœ ์ ‘๊ทผํ•ด์•ผ ํ•˜๊ณ  state ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ์—๋„ {this.state.fruit} ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

    //state ๊ฐ’ ๋ณ€๊ฒฝํ•˜๊ธฐ
    this.setState({fruit: 'banana'})
    
    //state ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
     <p>You're fruit is {this.state.fruit} !</p>

    ๋”์šฑ ๊ฐ„ํŽธํ•˜๊ณ  ์ง๊ด€์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ ๊ฒƒ์ด๋‹ค.

     

     

    ์ •๋ฆฌํ•˜์ž๋ฉด, useState ์˜ ์ธ์ž๋กœ ๋งŒ๋“ค state ์˜ ์ดˆ๊ธฐ๊ฐ’์„ ๋˜์ ธ์ฃผ๋ฉด, useState ๊ฐ€ state ์™€ state ๋ฅผ ๊ฐฑ์‹ ํ•  ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ๊ฒƒ!

    ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—ฌ๋Ÿฌ state ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด๋‘๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

      const [age, setAge] = useState(42);
      const [fruit, setFruit] = useState('banana');
      const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);

    useEffect

    React class์˜ componentDidMount ๋‚˜ componentDidUpdate, componentWillUnmount์™€ ๊ฐ™์€ ๋ชฉ์ ์œผ๋กœ ์ œ๊ณต๋˜์ง€๋งŒ, ํ•˜๋‚˜์˜ API๋กœ ํ†ตํ•ฉ๋œ ๊ฒƒ์ด๋‹ค.

    (์ฐธ๊ณ : 2021.03.21 - [PROGRAMMING/React] - React :: ์ƒ๋ช…์ฃผ๊ธฐ (Lifecycle))

     

    ์™œ ์ด๋“ค์„ ํ†ตํ•ฉํ–ˆ๊ณ , ๊ทธ๊ฒŒ ์žฅ์ ์ด ๋ ๊นŒ?

     

    ๋‹ค์Œ ๋‚ด์šฉ์„ ์ƒ๊ฐํ•ด๋ณด์ž.

     

    ๋ Œ๋”๋ง ์ดํ›„์— ํ•ญ์ƒ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธธ ๋ฐ”๋ž€๋‹ค๋ฉด, ์–ด๋–ค ์ƒ๋ช… ์ฃผ๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?

    ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ด์ œ ๋ง‰ ๋งˆ์šดํŠธ ๋œ ๊ฒƒ์ธ์ง€, ์•„๋‹ˆ๋ฉด ์—…๋ฐ์ดํŠธ๋œ ๊ฒƒ์ธ์ง€์— ์ƒ๊ด€์—†์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

    ๊ทธ๋Ÿผ, ์ƒ๋ช… ์ฃผ๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ƒ๊ฐํ–ˆ์„ ๋• componentDidMount์™€ componentDidUpdate ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

    ๊ทธ๊ฒƒ๋„ ๊ฐ™์€ ์ฝ”๋“œ๋กœ ์‹คํ–‰ํ•ด์•ผํ•œ๋‹ค. ๋‹ค์Œ์ฒ˜๋Ÿผ..

    class Example extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0
        };
      }
    
      componentDidMount() {
        document.title = `You clicked ${this.state.count} times`;
      }  
      
      componentDidUpdate() {
        document.title = `You clicked ${this.state.count} times`;
      }

    ์ด๋Š” ์ƒ๋‹นํžˆ ๋น„ํšจ์œจ์ ์ธ ๊ฒƒ์œผ๋กœ ๋ณด์ธ๋‹ค.

     

    ๋ฐ˜๋ฉด useEffect Hook ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋งค ๋ Œ๋”๋ง ์ดํ›„์— effects๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง๋„ ํฌํ•จํ•ด์„œ!

    (์šฐ๋ฆฌ๊ฐ€ React ์—๊ฒŒ ๋„˜๊ธด ์ด Hook ํ•จ์ˆ˜๋ฅผ 'effect' ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.)

     

    ๊ทธ๋ž˜์„œ ๊ทธ๋ƒฅ ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

     

    * useEffect Hook ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋จผ์ € React ๋กœ๋ถ€ํ„ฐ ๋ฐ›์•„์™€์•ผ ํ•œ๋‹ค.

    import React, { useState, useEffect } from 'react';
    function Example() {
      const [count, setCount] = useState(0);
    
      useEffect(() => {    
        document.title = `You clicked ${count} times`;  
      });

    ์ค‘๋ณต๋œ ์ฝ”๋“œ๋„ ์—†๊ณ , ๊ฐ€๋…์„ฑ๋„ ๋Š˜์—ˆ๋‹ค.

     

    useEffect ํŠน์ง•

    • ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.
      -> effect ๋ฅผ ํ†ตํ•ด state ๋ณ€์ˆ˜์™€ ๊ฐ์ข… prop ์—๋„ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋„๋ก!
    • ๋ Œ๋”๋ง ์ดํ›„์— ๋งค๋ฒˆ ์ˆ˜ํ–‰๋œ๋‹ค.
      (๋งˆ์šดํŠธ, ์—…๋ฐ์ดํŠธ๋ผ๋Š” ๊ฐœ๋…๋ณด๋‹ค๋Š” ๋ Œ๋”๋ง ์ดํ›„์— ๋ฐœ์ƒ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.)
      React ๋Š” effect ๊ฐ€ ์ˆ˜ํ–‰๋˜๋Š” ์‹œ์ ์— ์ด๋ฏธ DOM ์ด ์—…๋ฐ์ดํŠธ ๋˜์—ˆ์Œ์„ ๋ณด์žฅํ•œ๋‹ค.
    • useState์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ effect๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    Clean-Up

    ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ •๋ฆฌ(Clean-Up) ์ด effect ์— ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

    ๊ทธ๋Ÿด ๋• useEffect ์—์„œ ์ •๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ฉ๋‹ค.

     

    effect ๊ฐ€ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ฆฌ์•กํŠธ๋Š” ๊ทธ ํ•จ์ˆ˜๋ฅผ ์ •๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์‹คํ–‰์‹œํ‚จ๋‹ค.

    ์ด๋Š” (๊ธฐ๋ณธ์ ์œผ๋กœ) ํ•œ ๋ฒˆ์ด ์•„๋‹ˆ๋ผ, ๋ Œ๋”๋ง์ด ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค, ๋งค๋ฒˆ ๋ฆฌ๋ Œ๋”๋ง ์‹œ์— ์ •๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค.

     

     

     

    ์ฝ”๋“œ๋ฅผ ๋ณด์ž.

    import React, { useState, useEffect } from 'react';
    
    function FriendStatus(props) {
      const [isOnline, setIsOnline] = useState(null);
    
      useEffect(() => {    
        function handleStatusChange(status) {      
            setIsOnline(status.isOnline);    
          }    
        ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);    
        
        // effect ์ดํ›„์— ์–ด๋–ป๊ฒŒ ์ •๋ฆฌ(clean-up)ํ•  ๊ฒƒ์ธ์ง€ ํ‘œ์‹œํ•œ๋‹ค.    
        return function cleanup() {      
          ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);    
        };  
      });
      
      if (isOnline === null) {
        return 'Loading...';
      }
        
      return isOnline ? 'Online' : 'Offline';
    }

    ์ด ์ฝ”๋“œ๋Š” ์นœ๊ตฌ์˜ ์˜จ๋ผ์ธ ์ƒํƒœ๋ฅผ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ๋Š” ChatAPI ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•œ ์˜ˆ์ด๋‹ค.

    ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒซ ๋งˆ์šดํŠธ ๋ ๋•Œ๋ฅผ ํฌํ•จํ•˜์—ฌ, ๋งค๋ฒˆ ๋ฆฌ๋ Œ๋”๋ง ํ•  ๋•Œ๋งˆ๋‹ค ์นœ๊ตฌ ๊ตฌ๋…-๊ตฌ๋… ํ•ด์ง€๋ฅผ ๋ฐ˜๋ณตํ•œ๋‹ค.

     

     

    ์ด๋Š” ๋ฒ„๊ทธ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์„ฑ๋Šฅ ์ €ํ•˜(๋งค๋ฒˆ ์ •๋ฆฌํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰)๊ฐ€ ์šฐ๋ ค๋  ์ˆ˜ ์žˆ๋‹ค.

    ์ด ์ ๋“ค์„ ์‚ดํŽด๋ณด์ž.

     

    ๋ฒ„๊ทธ ๋ฐฉ์ง€

    ์ด์ „์˜ ์ฝ”๋“œ๋กœ ์–ด๋–ป๊ฒŒ ๋ฒ„๊ทธ ๋ฐฉ์ง€๊ฐ€ ๋˜๋ƒ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ,

    ๋งŒ์ผ ํ”„๋กœ๊ทธ๋žจ์ด ๋Œ์•„๊ฐ€๋Š” ์ค‘์— (์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜์–ด์žˆ๋Š” ๋™์•ˆ) ์นœ๊ตฌ์˜ id, ์ฆ‰ friend.id ๊ฐ€ ๋ฐ”๋€Œ์—ˆ์œผ๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

    ๋‹ค๋ฅธ ์นœ๊ตฌ์˜ ์˜จ๋ผ์ธ ์ƒํƒœ๋ฅผ ๊ณ„์† ํ‘œ์‹œํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ์ด๋Š” ๋ช…๋ฐฑํ•œ ๋ฒ„๊ทธ์ด๋‹ค.

     

    ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜€๋‹ค๋ฉด componentDidUpdate๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์ง€๋งŒ,

    useEffect ๋Š” ๋ฆฌ๋ Œ๋”๋ง ํ•  ๋•Œ๋งˆ๋‹ค , ๋‹ค์Œ์˜ effect ๋ฅผ ์ ์šฉํ•˜๊ธฐ ์ „์— ์ด์ „์˜ effect ๋Š” ์ •๋ฆฌํ•œ๋‹ค.

    ์ฆ‰ ์œ„์˜ ์ฝ”๋“œ์˜ ์‹คํ–‰ ๊ณผ์ •์„ ๊ฐ€์‹œํ™”ํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    // { friend: { id: 100 } } state์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์šดํŠธํ•œ๋‹ค.
    ChatAPI.subscribeToFriendStatus(100, handleStatusChange);     // ์ฒซ๋ฒˆ์งธ effect๊ฐ€ ์ž‘๋™ํ•œ๋‹ค.
    
    // { friend: { id: 200 } } state๋กœ ์—…๋ฐ์ดํŠธํ•œ๋‹ค..
    ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // ์ด์ „์˜ effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•œ๋‹ค.
    ChatAPI.subscribeToFriendStatus(200, handleStatusChange);     // ๋‹ค์Œ effect๊ฐ€ ์ž‘๋™ํ•œ๋‹ค.
    
    // { friend: { id: 300 } } state๋กœ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
    ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // ์ด์ „์˜ effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•œ๋‹ค.
    ChatAPI.subscribeToFriendStatus(300, handleStatusChange);     // ๋‹ค์Œ effect๊ฐ€ ์ž‘๋™ํžŒ๋‹ค.
    
    // ๋งˆ์šดํŠธ๋ฅผ ํ•ด์ œํ•œ๋‹ค.
    ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // ๋งˆ์ง€๋ง‰ effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•œ๋‹ค.

    ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š”, ์—…๋ฐ์ดํŠธ ๋กœ์ง (componentDidUpdate) ์„ ๋นผ๋จน์œผ๋ฉด์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฒ„๊ทธ๋ฅผ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค!

     

    ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฐœ์ƒ์ด ์šฐ๋ ค๋œ๋‹ค๋ฉด...

    ์นœ๊ตฌ id ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜์œผ๋ฉด ๊ตณ์ด ๊ตฌ๋… ํ•ด์ง€๋ฅผ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

    ๊ทธ๋ž˜์„œ ์œ„์˜ useEffect ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋ฉด ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

    useEffect(() => {
      function handleStatusChange(status) {
        setIsOnline(status.isOnline);
      }
    
      ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
      return () => {
        ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
      };
    }, [props.friend.id]); // props.friend.id๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งŒ ์žฌ๊ตฌ๋…ํ•œ๋‹ค.

    ์ด๋ ‡๊ฒŒ ํŠน์ • ๊ฐ’๋“ค์ด ๋ฆฌ๋ Œ๋”๋ง ์‹œ์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ฆฌ์•กํŠธ๋กœ ํ•˜์—ฌ๊ธˆ effect ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

    useEffect ์˜  ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ "์‹ ๊ฒฝ์“ฐ๋Š”" ๊ฒƒ์„ ๋„˜๊ฒจ์ฃผ๋ฉด ๋œ๋‹ค.

     

    ๋”ฐ๋ผ์„œ, ์œ„์˜ ์ฝ”๋“œ์—์„œ props.friend.id ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๊ตฌ๋…-์žฌ๊ตฌ๋… ์€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. (ํ•ด๋‹น effect ์‹คํ–‰ x)

     

    ๊ทธ๋Ÿฐ๋ฐ, ์ด ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐฐ์—ด์ด ์ปดํฌ๋„ŒํŠธ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋ฐ”๋€Œ๋Š” ๊ฐ’ + effect ์— ์˜ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฐ’์„ ๋ชจ๋‘ ํฌํ•จํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด์•ผ ํ•œ๋‹ค.

     

    ๋งŒ์ผ effect ๋ฅผ ๋งˆ์šดํŠธ์™€ ๋งˆ์šดํŠธ ํ•ด์ œ ์‹œ์— ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, useEffect ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋นˆ ๋ฐฐ์—ด([]) ์„ ๋„˜๊ฒจ์ฃผ๋ฉด ๋œ๋‹ค.

    (์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ componentDidMount์™€ componentWillUnmount ๋ชจ๋ธ์— ๋” ๊ฐ€๊น๋‹ค)

     

    Multiple useEffect

    ์—ฌ๋Ÿฌ effect ๋ฅผ ์„ค์ •ํ•ด์„œ ๊ฐ effect ๊ฐ€ ํ•˜๋Š” ์ผ์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒ๋ช… ์ฃผ๊ธฐ API ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” '์‹œ๊ธฐ'์— ๋งž์ถฐ์„œ ๊ธฐ๋Šฅ์„ ๋‹ค ๋„ฃ์–ด์•ผ ํ–ˆ์ง€๋งŒ, useEffect ๋Š” '๊ธฐ๋Šฅ'์— ๋งž์ถฐ์„œ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ์ฆ‰, ๊ตฌ๋…์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ œ๊ฑฐํ•˜๋Š” ๋กœ์ง๊ณผ ๊ฐ™์ด ์„œ๋กœ ๊ด€๋ จ ์žˆ๋Š” ์ฝ”๋“œ๋“ค์„ ํ•œ๊ตฐ๋ฐ์— ๋ชจ์•„์„œ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

    function FriendStatusWithCounter(props) {
      const [count, setCount] = useState(0);
      useEffect(() => {    
        document.title = `You clicked ${count} times`;
      });
    
      const [isOnline, setIsOnline] = useState(null);
      useEffect(() => {    
        function handleStatusChange(status) {
          setIsOnline(status.isOnline);
        }
    
        ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
        return () => {
          ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
        };
      });
      // ...
    }

    ์‚ฌ์šฉ์ž ์ •์˜ Hook

    ์‚ฌ์šฉ์ž ์ •์˜ Hook ์„ ๋งŒ๋“ค์–ด๋‘๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    • ์ด๋ฆ„์ด use๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ•จ์ˆ˜์ด๋‹ค.
    • ๋‹ค๋ฅธ Hook์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์กฐ๊ฑด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ์–ด์•ผ ํ•œ๋‹ค.
    • ๊ฐ™์€ Hook์„ ์‚ฌ์šฉํ•˜๋Š” ๋‘ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋Š” state๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š”๋‹ค

    ์œ„์—์„œ ๊ณ„์† ์‚ดํŽด๋ณธ ์˜ˆ์ œ์—์„œ ์นœ๊ตฌ์˜ ์ƒํƒœ๋ฅผ ๊ตฌ๋…ํ•˜๊ณ , ์˜จ๋ผ์ธ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ๋„ ์“ฐ์ผ ์ˆ˜ ์žˆ๋‹ค.

    ๊ทธ๋Ÿผ ๊ทธ ๋ถ€๋ถ„์„ ์‚ฌ์šฉ์ž ์ •์˜ Hook ๋กœ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–จ๊นŒ?

     

    import { useState, useEffect } from 'react';
    
    function useFriendStatus(friendID) {  const [isOnline, setIsOnline] = useState(null);
    
      useEffect(() => {
        function handleStatusChange(status) {
          setIsOnline(status.isOnline);
        }
    
        ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
        return () => {
          ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
        };
      });
    
      return isOnline;
    }

     

    ์ด useFriendStatus Hook์˜ ๋ชฉํ‘œ๋Š” ์นœ๊ตฌ์˜ ์ƒํƒœ๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    ์ด๋ฅผ ์œ„ํ—ค friendID๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๊ณ  ์˜จ๋ผ์ธ ์ƒํƒœ์˜ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

     

    ์ด์ œ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์ด Hook ์„ ๊ฐ€์ง€๊ณ  ๋…๋ฆฝ์ ์œผ๋กœ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

    Hook์€ state ๊ทธ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, ์ƒํƒœ ๊ด€๋ จ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ Hook ํ˜ธ์ถœ์€ ์™„์ „ํžˆ ๋…๋ฆฝ๋œ state๋ฅผ ๊ฐ€์ง€๊ณ , ์‹ฌ์ง€์–ด๋Š” ํ•œ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๊ฐ™์€ custom Hook์„ ๋‘ ๋ฒˆ ์“ธ ์ˆ˜๋„ ์žˆ๋‹ค.

     

    Custom Hook์€ ๊ธฐ๋Šฅ์ด๋ผ๊ธฐ๋ณด๋‹ค๋Š” ์ปจ๋ฒค์…˜(convention)์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„์ด ”use“๋กœ ์‹œ์ž‘ํ•˜๊ณ , ์•ˆ์—์„œ ๋‹ค๋ฅธ Hook์„ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด ๊ทธ ํ•จ์ˆ˜๋ฅผ custom Hook์ด๋ผ๊ณ  ๋ถ€๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. useSomething์ด๋ผ๋Š” ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜์€ linter ํ”Œ๋Ÿฌ๊ทธ์ธ์ด Hook์„ ์ธ์‹ํ•˜๊ณ  ๋ฒ„๊ทธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. - React ๊ณต์‹ ๋ฌธ์„œ

     

    ๊ทธ๋ž˜์„œ ์ € ์‚ฌ์šฉ์ž ์ •์˜ Hook ์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    function FriendStatus(props) {
      const isOnline = useFriendStatus(props.friend.id);
      if (isOnline === null) {
        return 'Loading...';
      }
      return isOnline ? 'Online' : 'Offline';
    }
    function FriendListItem(props) {
      const isOnline = useFriendStatus(props.friend.id);
      return (
        <li style={{ color: isOnline ? 'green' : 'black' }}>
          {props.friend.name}
        </li>
      );
    }

    Reference

    React ๊ณต์‹ ๋ฌธ์„œ

    ko.reactjs.org/docs/hooks-overview.html

    ko.reactjs.org/docs/hooks-effect.html

    ko.reactjs.org/docs/hooks-custom.html

    .

    'PROGRAMMING > React' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

    React :: ์ƒ๋ช…์ฃผ๊ธฐ (Lifecycle)  (0) 2021.03.21
    React :: Component, Props, State  (0) 2021.03.20
    React :: Element Rendering (์—˜๋ฆฌ๋จผ๋“œ ๋ Œ๋”๋ง)  (0) 2021.03.20
    React : JSX  (0) 2021.03.20
    React :: React ์‹œ์ž‘ํ•˜๊ธฐ  (0) 2021.03.20

    ๋Œ“๊ธ€

Designed by Tistory.