Hooks

sese·2022년 10월 4일

새싹

목록 보기
20/39

[ Hook 란? ]

클래스형 컴포넌트에서만 사용 가능했던 statelifecycle 을 함수형 컴포넌트에서도 사용 가능하도록 도와주는 기능


[ Hooks 종류 ]

1. useState()

  • 가장 기본적인 Hook 으로 함수형 컴포넌트에서 가변적인 상태를 지니게 해준다.
  • 클래스형 컴포넌트에서의 State
import React, { useState } from 'react';

function StateFunction() {
    // [state명, setter함수] = useState(초기값)
    // useState의 초기값은 숫자일 수도, 문자일 수도, 배열일 수도 있다.
    const [msg, setMsg] = useState("");
    const [list, setList] = useState([]);

    function changeMsg() {
        setMsg("메세지");
    }

    return (
        <div>
            <p>{msg}</p>
            <button onClick={changeMsg}>클릭</button>
        </div>
    )
}

export default StateFunction;

2. useEffect()

  • 컴포넌트가 렌더링 될 때마다 특정 작업을 수행할 수 있게 해준다.
  • 클래스형 컴포넌트의 componentDidMountcomponentDidUpdate 가 합쳐진 형태
import {useState, useEffect} from 'react';

const Hook = ()  => {
    const [name, setName] = useState("");
    const [cnt, setCnt] = useState(0);

    const changeName = e => {
        setName(e.target.value);
    }

    const changeCnt = () => {
        setCnt(cnt + 1);
    }

    // 컴포넌트가 rendering 될 때마다 특정 작업을 수행
    useEffect(() => {
        console.log("렌더링이 완료되었습니다.");
    })
  	
    // 두번째 인자로 빈 배열을 보내면, Mount 될 때만 실행된다.
    useEffect(() => {
        console.log("최초 rendering");
    }, [])
	
    // 특정 값이 바뀔 때만 실행하고 싶다면, 배열에 값을 넣어주면 된다.
    // Mount 될 때는 항상 실행된다.
    useEffect(() => {
        console.log('name값 변경');
        // cleanup(뒷정리) 함수 : 렌더링 되기 직전에 실행된다.
        return () => {
            console.log("name2 : ", name);
        }
    }, [name])

    return(
        <div>
            <div>
                <input value={name} onChange={changeName}></input>
                <button onClick={changeCnt}>+1</button>
            </div>
            <h3>이름 : {name}</h3>
            <h3>횟수 : {cnt}</h3>
        </div>
    )
}

export default Hook;

3. useReducer()

  • useState() 처럼 State 를 관리할 수 있게 해준다.
  • useReducer() 를 사용하면 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼 수 있다.
import {useReducer} from 'react';

// reducer() : 현재 상태와 업데이트를 위해 필요한 정보를 담은 액션 값을 전달받아 새로운 상태를 반환하는 함수
function reducer(state, action) {
    switch (action.type) {
        case "INCREMENT":
            return {value: state.value + 1};
        case "DECREMENT":
            return {value: state.value - 1};
        default:
            return state;
    }
}

const Reducer = () => {
    // useReducer(reducer 함수, 초기값) -> state.value = 0
    const [state, dispatch] = useReducer(reducer, {value: 0});
    // state = 현재 가리키고 있는 상태
    // dispatch = 액션을 발생시키는 함수

    return(
        <div>
            <h1>{state.value}</h1>
            {/* dispatch 함수 실행 */}
            <button onClick={() => {dispatch({type: "DECREMENT"})}}>-1</button>
            <button onClick={() => {dispatch({type: "INCREMENT"})}}>+1</button>
        </div>
    )
}

export default Reducer;

4. useMemo()

  • 함수형 컴포넌트 내부에서 발생하는 연산을 최적화시켜주는 Hook
  • Rendering 과정에서 특정 값이 바뀌었을 때만 연산을 실행한다.
import {useState, useMemo} from 'react';

function getAverage(list) {
    console.log("getAverage");
    let sum = 0;
    if (list.length == 0) return sum;
    for (let i=0; i<list.length; i++) {
        sum = sum + list[i];
    }
    return sum / list.length;
}

const Memo = () => {
    const [list, setList] = useState([]);
    const [num, setNum] = useState("");

    // input창에 입력될 때마다 State가 업데이트 된다.
    const onChange = e => {
        console.log("onChange");
        setNum(e.target.value);
    }

    const onInsert = e => {
        setList([...list, parseInt(num)]);
        setNum(0);
    } 
    
    // State가 업데이트 되어 재렌더링 될 때마다 함수가 재선언되어 getAverage 함수가 계속 실행된다.
    const avg = getAverage(list);
  	
  	// useMemo() 사용
    // list값이 업데이트 됐을 때만 getAverage 함수가 실행된다.
    const avg = useMemo(() => {getAverage(list)}, [list]);

    return(
        <div>
            <input value={num} onChange={onChange}/>
            <button onClick={onInsert}>등록</button>

            <ul>
                {list.map((v, i) => {
                    <li key={i}>{v}</li>
                })}
            </ul>

            <div>
                <b>평균값 : {avg}</b>
            </div>
        </div>
    )
}

export default Memo;

5. useCallback()

  • Rendering 최적화에 사용되는 Hook API
  • 재렌더링 될 때 함수를 다시 불러오는 것을 막는다.
import {useState, useCallback} from 'react';

// 위의 onChange 함수와 onInsert함수에 useCallback을 사용하였다.

// onChange함수에서는 State가 사용되지 않았기 때문에 빈 배열을 보내 Mount 될 때만 함수가 선언되게 해주었다.
const onChange = useCallback(e => {
  console.log(e.target.value);
  setNum(e.target.value);
}, []);

// onInsert함수에서는 num과 list가 사용되었기 때문에 num과 list값이 업데이트 될 때마다 해당 함수가 필수로 재선언되어야 한다.
const onInsert = useCallback(e => {
  setList([...list, parseInt(num)]);
  setNum("");
}, [num, list]);

6. useRef()

  • 함수형 컴포넌트에서 ref 를 사용하기 쉽게 만들어주는 Hook
import {useRef} from 'react';

const Ref = () => {
  
    // useRef(초기값) : 보통 useRef(null)
    const input = useRef();

    const onInsert = e => {
        // ref.current로 현재 가리키는 객체에 접근할 수 있다.
  		input.current.focus();
    } 

    return(
        <div>
            // ref={}
            <input value={num} onChange={onChange} ref={input}/>
            <button onClick={onInsert}>등록</button>

            <ul>
                {list.map((v, i) => {
                    <li key={i}>{v}</li>
                })}
            </ul>

            <div>
                <b>평균값 : {avg}</b>
            </div>
        </div>
    )
}

export default Ref;
profile
예전 글은 다크모드로 봐야 잘 보일 수도 있습니다.

0개의 댓글