xtring.dev

[React] Functional Component에서 Hooks를 사용하자. (useState, useEffect) 본문

Front-End/React

[React] Functional Component에서 Hooks를 사용하자. (useState, useEffect)

xtring 2020. 6. 24. 16:45

React

 

 

 

React Hooks는 Functional Component에서 Class-type Component의 LifeCycle의 동작 방식을 가능하게 해줍니다.

Hooks는 React 16.8에서 새롭게 추가되었습니다. 그리고 Class 작성 없이 state와 React의 특성을 사용하게 해주었습니다.

Hooks를 사용하기 위해서는 반드시 지켜줘야하는 몇가지 규칙이 존재합니다. 그리고 자동으로 이 규칙을 강요하게 해주는 linter plugin이 존재합니다.

 

 

 

 

Rules of Hooks

Only Call Hooks at the Top Level

Hooks를 사용할 때는 꼭 맨 위에서 호출하라!

Hooks는 loops, conditions, nested functions 안에서 호출하면 안됩니다. 대신 React 함수의 맨 위에서 Hooks를 사용합니다. 이 규칙을 따르게 되면 구성 요소(Component renders)가 렌더링 될 때마다 Hooks가 동일한 순서로 호출됩니다. 이것이 React가 여러 useState와 useEffect 호출 간에 Hooks의 state(상태)를 올바르게 보존할 수 있게 하는 것입니다.

 

 

 

Only Call Hooks from React Function

꼭 React 함수로부터 Hooks를 호출하라!

일반적인 JavaScript function들로부터 Hooks를 호출하지 마세요. 대신에 아래의 것들을 할 수 있습니다.

  • React function component들로 부터 Hooks를 호출
  • Custom Hooks(커스텀 훅)에서 Hooks를 호출

이와 같은 규칙을 따르게 되면, 구성 요소의 모든 상태 저장 논리를 소스 코드에서 명확하게 볼 수 있습니다.

 

 

 

State Hook

Hooks를 통해서 Functional Components에서도 State를 다루는 것이 가능해졌습니다. 먼저 아래 코드를 확인해 볼까요?

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useState()를 통해서 state를 초기화하는 방법은 ES6의 구조분해할당(Destructuring assignment)을 생각하시면 됩니다. 예제를 살펴보면 count는 state를 담고 있으며 setCount()를 통해 업데이트합니다.

count -> state
setCount(/* 업데이트 할 state */)

또한 useState는 사용 수에 대한 제한이 없습니다.

 

 

 

Effect Hook

Class-type Component의 LifeCycle을 Functional Component에서도 사용하기 위해 useEffect() 함수가 추가되었습니다.

useEffect는 컴포넌트가 마운트(mount) 되었을 때(componentDidMount), 컴포넌트가 업데이트 되었을 때(componentDidUpdate), 컴포넌트가 마운트 해제될 때(componentWillUnmount) 세가지 경우의 LifeCycle과 같은 동작 방식으로 사용할 수 있습니다.

 

 

  1. componentDidMount()와 componentDidUpdate()와 같이 사용하기

    import React, { useState, useEffect } from 'react';
    function Example() {
    const [count, setCount] = useState(0);
    
    // Similar to componentDidMount and componentDidUpdate:
    useEffect(() => {
     // Update the document title using the browser API
     document.title = `You clicked ${count} times`;
    });
    return (
     <div>
       <p>You clicked {count} times</p>
       <button onClick={() => setCount(count + 1)}>
         Click me
       </button>
     </div>
    );
    }

    위의 예제는 componentDidMount와 ComponentDidUpdate 처럼 동작하는 Effect Hook 사용방법입니다. 위 예제를 실행 시켜보면 컴포넌트가 렌더링 될 때마다 호출되는 것을 확인할 수 있습니다.

 

  1. componentWillUpdate() 처럼 사용하기

    import React, { useState, useEffect } from 'react'; 
    function FriendStatus(props) { 
     const [isOnline, setIsOnline] = useState(null); 
    
     function handleStatusChange(status) {
         setIsOnline(status.isOnline); 
     }
    
     useEffect(() => { 
         ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); 
    
         return () => { 
             ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); 
         }; 
     }); 
    
     if (isOnline === null) { 
         return 'Loading...'; 
     } 
     return isOnline ? 'Online' : 'Offline'; 
    }

    이번에는 Effect Hook 함수를 반환합니다. 반환되는 함수는 컴포넌트가 마운트 해제될 때(componentWillUnmount)나 컴포넌트가 업데이트(componentWillUpdate)되어 다음 effect가 호출되기 이전에 호출됩니다.

 

  1. componentDidMount 처럼 사용하기
    import React, { useState, useEffect } from 'react'; 
    
    function ComponentDidMountExample(props) {
    	useEffect(() => {
    		TestAPI.request();
    	}, []);
       
    	return ( 
    	    <div> 
            	test 
    	    </div> 
    	); 
    }

  useEffect의 두번째 인자로 props나 state 값을 배열 형태로 넣어줄 수 있습니다. 그리고 두 번째 인자에 들어간 값들이 변경 되었을 때만 Effect Hook이 호출됩니다. 하지만 빈 배열을 가진 Effect Hook은 props와 state의 업데이트를 감시하고 있지 않기 때문에 componentDidMount와 같이 렌더링 시 한번만 실행하는 동작 방식을 보여줍니다.

반응형
Comments