[React] React Hook의 개념과 종류 - useState(), useEffect()

    Hooks


    Function Component와 Hook

    컴포넌트의 종류로는 Function Component와 Class Component가 있다.

     

    1. Function Component
      • state 사용 불가
      • Lifecycle에 따른 기능 구현 불가
      • Hooks
    2. Class Component
      • 생성자에서 state를 정의
      • setState() 함수를 통해 state 업데이트
      • Lifecycle methods 제공

     

    Hook을 사용하면, Function Component도 Class Component의 기능을 모두 동일하게 사용할 수 있다.

     

     

    Hook 의미 및 특징

    • Hook, 갈고리 ➰ 기존에 사용하던 기능에 갈고리를 거는 것처럼 끼어 들어가 같이 수행되는 것.
    • React Hook : 리액트의 state와 생명 주기 기능에 갈고리를 걸어 원하는 시점에 정해진 함수를 실행되도록 만든 것
    • 'use-'로 시작한다.

     

    Hook의 종류 - 1


    useState()

    state 사용하기 위한 Hook

     

    📌예제1-1. 클릭 수 세기 - 함수에 변수(count)를 선언

    import React, { useState } from "react";
    
    function Counter(props) {
        var count = 0;
    
        return (
            <div>
                <p>총 {count}번 클릭했습니다.</p>
                <button onClick={() => count++}>
                    클릭
                </button>
            </div>
        )
    }

    함수에 변수(count)를 선언해서 사용하는 경우
    ⏩ count 수는 증가시킬 수 있지만, 바뀐 count의 수가 재렌더링되지는 않는다. → 화면 변화 ❌

    ✅ state를 사용해서 값이 바뀔 때마다 다시 렌더링해야 한다. → useState() 사용

     

    사용법

    const [변수명, set함수명] = useState(초기값);

    • 파라미터로, 선언할 state의 초기값이 들어간다.
    • 배열을 리턴한다.
    • const[변수명, set함수명]
      ✅ [ state로 선언된 변수, 해당 state의 set함수 ]

     

    📌예제1-2. 예제1-1 변형 - useState() 사용

    // 📌예제2. 예제1 변형
    
    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>
        )
    }
     
    • 클래스 컴포넌트에선 setState()로 모든 state 값을 업데이트할 수 있었지만,
    • 함수 컴포넌트에서는 변수 각각에 대해 set 함수가 따로 존재한다!

     

    useEffect()

    Side effect를 수행하기 위한 Hook

     

    Side effect : 효과, 영향

    서버에서 데이터를 받아오거나, 수동으로 돔을 변경하는 등의 작업을 의미한다.
    'Side effect'라 부르는 이유는 렌더링 중에는 작업이 완료될 수 없기 때문이다(Side). 
    즉, 렌더링이 끝난 이후에 실행되어야 하는 작업들이 여기에 해당한다.
    다른 컴포넌트에 영향을 미칠 수 있으며(effect), 사이드로 실행되어야 한다는 의미에서 'Side effect'라고 부른다.

     

    정의

    리액트의 함수 컴포넌트에서 Side effect를 실행할 수 있게 해주는 Hook

     

    특징

    클래스 컴포넌트에서 제공하는 생명 주기들(componentDidMount, componentDidUpdate, componentDidUnmount)과

    동일한 기능을 하나로 통합해서 제공한다. 

     

    사용법

    useEffect(이펙트 함수, 의존성 배열);

    • 의존성 배열 : 해당 이펙트가 의존하고 있는 배열로. 배열 안의 값이 하나라도 변경되면 이펙트 함수가 실행된다.
    • 기본적으로 이펙트 함수는,
      • 처음 컴포넌트가 렌더링된 이후,
      • 업데이트한 컴포넌트가 다시 렌더링 된 이후
      실행된다.

     

    useEffect(이펙트함수, [])

    이펙트 함수가 mount, unmout시에 단 한 번씩만 실행되도록 하고 싶을 경우, 의존성 배열에 빈 배열을 할당한다.

     

    useEffect(이펙트함수)

    의존성 배열을 생략하면, 컴포넌트가 업데이트 될 때마다 호출된다.

     

    📌 예제2-1. useEffect() - 의존성 배열 생략

    import React, { useState, useEffect } from "react";
    
    function Counter(props) {
        const [count, setCount] = useState(0);
    
        // componentDidMount, componentDidUpdate와 비슷하게 작동
        useEffect(()=>{
          // 브라우저 API를 이용해서 document의 title을 업데이트 
          document.title = `You clicked ${count} times`;
        })
        return (
            <div>
                <p>총 {count}번 클릭했습니다.</p>
                <button onClick={() => setCount(count + 1)}>
                    클릭
                </button>
            </div>
        )
    }
    • 의존성 배열 없음 → DOM이 변경될 때마다 이펙트 함수 실행
    • 해당 컴포넌트 안에서 선언되기 때문에, 해당 컴포넌트의 props와 state에 접근 가능

    📌 예제2-2. useEffect - return 함수 사용

    import React, { useState, useEffect } from "react";
    
    function UserStatus(props) {
      const [isOnline, setIsOnline] = useState(null)
    
      function handleStatusChange(status) {
        setIsOnline(status.isOnline);
      }
    
      useEffect(()=>{
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
          ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
          // 컴포넌트가 unmount 될 때 호출됨
        }
      })
    
      if(isOnline===null){
        return '대기 중...';
      }
      return isOnline ? "온라인" : "오프라인";
    }
    useEffect(() =>{
        return () => {}
        // componentWillUnmount와 같다.
    })

     

    📌 예제2-3. 컴포넌트에 여러 개의 useEffect Hook 사용하기

     

    import React, { useState, useEffect } from "react";
    
    function UserStatusWithCounter(props) {
      const [count, setCount] = useState(0);
      useEffect(()=>{
        document.title = `총 ${count}번 클릭했습니다.`;
      })
    
      const [isOnline, setIsOnline] = useState(null)
    
      useEffect(()=>{
        ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
        return () => {
          ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
        }
      }) 
      function handleStatusChange (status) {
        setIsOnline(status.isOnline)
      }
    }

    useEffect Hook은 하나의 컴포넌트에 여러 개의 hook을 사용할 수 있다.

     

    Summary

    useEffect(() => {
      // 컴포넌트가 마운트 된 이후
      // 의존성 배열에 있는 변수들 중 하나라도 값이 변경되었을 때 실행됨
      // 의존성 배열에 빈 배열을 넣으면, 마운트와 언마운트 시에 단 한 번씩만 실행됨
      // 의존성 배열 생략 시 컴포넌트 업데이트시마다 실행됨
      ...
    
      return () => {
        // 컴포넌트가 마운트 해제되기 전에 실행됨
        ...
      }
    }, [의존성 변수1, 의존성변수 2, ...]) 


    🚀 참고

    댓글