티스토리 뷰

1. Hook 개요

2. State Hook 사용하기

3. Effect Hook 사용하기

4. Context Hook 사용하기


1. Hook 개요

[그림 1] React Hooks

Hook은 함수 컴포넌트에서 React state와 생명주기 기능(lifecycle)을 "연동(hook into)"할 수 있게 해주는 함수이다.

Hook은 class 안에서는 동작하지 않는다. Hook은 class를 작성하지 않고도 state와 다른 React의 기능들을 사용할 수 있게 해준다.

(Hook은 React 16.8에 새로 추가된 기능이다.)

 

Hook은 일반적인 JavaScript 함수이지만, 두 가지 규칙을 준수해야 한다.

  • 최상위(at the top level)에서만 Hook을 호출해야 한다. 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행할 수 없다.
  • React 함수 컴포넌트 내에서만 Hook을 호출해야 한다. 일반 JavaScript 함수에서는 Hook을 호출하면 안된다.

 

 

2. State Hook 사용하기

import React, {useState} from 'react';

const State = () => {
    const [value, setValue] = useState('hello');
    const [count, setCount] = useState(0);
    const handleClick = () => {
        setValue('jenny');
    };
    return(
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>Click me</button>
            <button onClick={handleClick}>버튼</button>
            {value}
        </div>
    )
};

export default State;

여기서 useState()가 바로 Hook이다. Hook을 호출해 함수 컴포넌트 안에 state를 추가했다. 이 state는 컴포넌트가 다시 렌더링 되어도 그대로 유지된다.

 

useState는 현재의 state 값과 이 값을 업데이트하는 함수를 쌍으로 제공한다. 이 함수는 이벤트 핸들러나 다른 곳에서 호출할 수 있다. 이는 class의 this.setState와 거의 유사하지만, 이전 state와 새로운 state를 합치지 않는다는 차이점이 있다.

 

useState는 인자로 초기 state 값을 하나 받는다. useState('hello') 가 쓰인 곳에서는 state의 value 값을 hello로 초기 지정하였다. useState(0)이 쓰인 부분에서는 state의 count 초기값을 0으로 하겠다는 것이다.

 

[그림 2] state hook 코드가 화면에 렌더링된 모습

'Click me' 버튼을 클릭할 때 마다 count 값이 1씩 증가하게 되어 그때의 count 값이 You clicked n times의 n으로 나타난다.

 

'버튼' 을 클릭하면 value가 'hello'에서 'jenny'로 바뀌면서 화면에도 'jenny' 글자가 나타난다.

 

 

3. Effect Hook 사용하기

import React, {useState, useEffect} from 'react';

const Effect = () => {
    const [count, setCount] = useState(0);
    useEffect(() => {
        document.title = 'jenny';
        console.log('hello world');
        // return () => {
        //     console.log('bye');
        // }
    }, []);
    return(
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount((prev) => prev + 1)}>
                Click me
            </button>
        </div>
    )
};

export default Effect;

React 컴포넌트 안에서 데이터를 가져오거나 DOM을 직접 조작하는 작업을 할 수 있다. 이런 모든 동작을 "side effects(또는 effects)"라고 한다. 왜냐하면 이러한 동작들이 컴포넌트에 영향을 줄 수도 있고, 렌더링 과정에서는 구현할 수 없는 작업이기 때문이다.

 

Effect Hook, 즉 useEffect는 함수 컴포넌트 내에서 이런 side effects를 수행할 수 있게 해준다. React class의 componentDidMount나 componentDidUpdate, componentWillUnmount와 같은 목적으로 제공되지만, 하나의 API로 통합된 것이다.

 

위의 코드를 살펴보면, useEffect는 Effect라는 함수 컴포넌트 안에 선언되어 있기 때문에 props와 state에 접근할 수 있다. 기본적으로 React는 매 렌더링 이후에 effects를 실행한다.

 

위 코드의 경우는 componentDidMount와 같다. 즉, 최초에 컴포넌트가 마운트 될 때 1번만 실행된다.

 

useEffect(() => {}, [count])와 같이 [] 안에 state 값을 넣으면 (최초 렌더링 했을 때를 포함) 해당 state 값이 바뀔 때 마다 useEffect가 실행된다. 이 경우는 componentDidUpdate와 같다.

 

위 코드의 주석을 해제하면 componentWillUnmount와 같아진다. 즉, 컴포넌트가 소멸된 시점에 (DOM에서 삭제된 후) 실행된다. 컴포넌트 내부에서 타이머나 비동기 API를 사용하고 있을 때, 이를 제거하기에 유용하다.

 

 

4. Context Hook 사용하기

import React, { useState, createContext, useContext } from "react";

export const Global = createContext();

const D = () => {
    const {name, setName} = useContext(Global);
    return(
        <>
            hello world {name}
            <button onClick={() => setName('jiyoung')}>ChangeName</button>
        </>
    )
};

const C = ({name}) => {
    return(
        <D name={name}/>
    )
};

const B = ({name}) => {
    return(
        <C name={name}/>
    )
};

const A = ({name}) => {
    return(
        <B name={name}/>
    )
};

const Context = () => {
    const [name, setName] = useState('jenny');
    const obj = {
        name,
        setName
    };
    return(
        <>
            <Global.Provider value={obj}>
                <A name={name}/>
            </Global.Provider>
        </>
    )
};

export default Context;

useContext는 context 객체(React.createContext에서 반환된 값)을 받아 그 context의 현재 값을 반환한다. context의 현재 값은 트리 안에서 이 Hook을 호출하는 컴포넌트에 가장 가까이에 있는 <Global.Provider>의 value prop에 의해 결정된다.

 

컴포넌트에서 가장 가까운 <Global.Provider>가 갱신되면 이 Hook은 그 Global provider에게 전달된 가장 최신의 context value를 사용하여 다시 렌더링 되게 한다. 상위 컴포넌트에서 React.memo 또는 shouldComponentUpdate를 사용하더라도 useContext를 사용하고 있는 컴포넌트 자체에서부터 다시 렌더링된다.

 

useContext로 전달한 인자는 context 객체 그 자체여야 한다. useContext(Global)과 같은 형태로 사용해야 하고, useContext(Global.Provider)나 useContext(Global.Consumer)처럼 사용할 수 없다.

 

useContext를 호출한 컴포넌트는 context 값이 변경되면 항상 리렌더링 된다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
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
글 보관함