본문 바로가기
Programming/React

[REACT] 훅. Hook

by 공부합시다홍아 2024. 5. 14.
 

[REACT] 컴포넌트 반복

[REACT] React Event[REACT] STATE[REACT] 컴포넌트(Components)와 Props[REACT] 코드 살펴보기[REACT] REACT 란REACT리액트는 자바스크립트 라이브러리이다. 구조가 MVC, MVVM과 같은 다른 프레임워크등과는 다르게 오직

hong-study.tistory.com


훅(Hook) 이란?

  • 리액트 컴포넌트는 클래스형 컴포넌트(Class component)와 함수형 컴포넌트(Functional component)로 나뉜다.
  • 리액트 훅은 새로운 기능으로 React 16.8버전에 새로 추가된 기능이다.
  • 함수형태의 컴포넌트에서 사용되는 몇가지 기술을 Hook이라고 부릅니다. (useState, userEffect 등)
  • 리액트 훅은 함수형 컴포넌트가 클래스형 컴포넌트의 기능을 사용할 수 있도록 해주는 기능이다.

혹의 규칙

  • 최상위에서만 Hook을 호출해야 한다.
    • 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안된다.
    • 이 규칙을 따르면 컴포넌트가 렌더링될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.
  • 리액트 함수 컴포넌트에서만 Hook을 호출해야 한다.
반드시 알아야 할 기본 훅

useState(초기값)

const [date, setDate] = userState("초기값")
※ useState() : 배열 반환 첫 번째 배열의 요소에는 현재 값을, 두번 째 요소는 상태를 변경하는 (setter)를 반환

useEffect(실행시킬 콜백함수, 값에 따른 렌더링 지정 배열)

useEffect의 첫 번째 매개변수는 실행시킬 콜백 함수이다.
useEffect의 두 번째 매개변수는 배열[]을 사용하여 특정 값이 update 될 때만 실행시켜 줄 수 있다.
useEffect()는 컴포넌트의 라이프 사이클을 다룬다.
▶ react 컴포넌트가 mount, mount 이후, unmount때 마다 특정작업을 수행
useEffect()는 여러 개 일 수도 있다.

렌더링(화면을 지웠다 다시 생성)은 아래와 같은 상황에 발생된다.

리렌더링을 야기하는 요인

  • setState에 의한 state 변경
  • 상위 컴포넌트에서 전달받은 Props의 변경
  • 상위 컴포넌트 리렌더링 ▶ 하위 컴포넌트 리렌더링
  • Provider의 value prop가 바뀔 때, Context.Provider 하위에서 해당 컴포넌트를 구독하고 있는 모든 컴포넌트 리렌더링 (※ ContextAPI 공부필요)
  • 리덕스 스토어의 state에 변경 발생 시, useSelector를 사용해서 리덕스 스토어의 state를 조회하는 컴포넌트 리렌더링

라이프 사이클 ( 클래스형 컴포넌트 기준 )

랜더링 이후에 실행시킬 작업이 있으면 아래 함수를 사용한다.

  • componentDidMount : 컴포넌트가 마운트 됨, 즉 컴포넌트의 첫번째 렌더링이 마치면 호출되는 메서드
  • componentDidUpdate : state의 변경, props의 변경 이후 실행되는 메서드
  • componentWillUnmount : 컴포넌트가 리렌더링 되기직전(언마운트) 시점에 실행되는 메서드
  • 이외에도 여러가지가 있다.

클래스형 componentDidMount() 대체

함수형 훅

useEffect( () => {
	console.log(`렌더링완료`);
});

mount 이후 업데이트 될 때는 실행되지 않으려면, 두번째 매개변수 배열를 줍니다.

useEffect( () => {
	console.log(`처음만 실행됩니다`);
}, []);

※ update 이후 - 특정값에 의해 컴포넌트가 업데이트 되고 난 후 발생합니다.

클래스형 componentDidUpdate() 대체

함수형 훅

const HookEffect = () => {
    //useState
    const[name, setName] = useState('');
    const handleName = (e) => {
        setName( e.target.value );
    }

    //특정값이 업데이트 될 때만 실행해주려면 두번째 매개변수에 값을 state값을 지정합니다
    useEffect( () => {
        console.log(`name이 업데이트 시 실행됩니다`)
    }, [name]);

    return (
        <div>
            
            이름:<input type="text" onChange={handleName}/><br/>
            이름:{name}
        </div>
    )
}

export default HookEffect;
주의 할 점
useEffect안에서 객체타입 state를 setState하는 경우 무한루프에 빠질 수 있다.
해결 방안은 아래의 문서로 제시한다.
https://kinsta.com/knowledgebase/react-hook-useeffect-has-a-missing-dependency/
 

How To Fix the “React Hook useEffect Has a Missing Dependency” Error

Learn 3 different ways to fix the common error that developers encounter, the “React Hook useEffect has a missing dependency" error.

kinsta.com

무한 루프 코드

function Test() {
    //useState
    const[name, setName] = useState({name: '홍길동'});

    //아래코드는 무한루프를 발생시킵니다.
    useEffect( () => {
	
        const copy = {...name }; //객체 전개구문( 객체복사)
        setName(copy) //주소값이 변했다고 판단되어 다시 렌더링을 실행
    }, [name]);

    return (
        <div>
						생략...
        </div>
    )
}


export default Test

※ unmount직전 - 컴포넌트가 화면에서 사라지기 직전에 호출된다.

클래스형 componentWillUnMount() 대체

함수형

const HookEffect = () => {
    //useState
    const[name, setName] = useState('');
    const handleName = (e) => {
        setName( e.target.value );
    }
    
	//useEffect    
    useEffect( () => {
        console.log(`name이 업데이트 시 실행됩니다`)
        
        //unmount이후 실행됩니다.
        return () => {
            console.log(`unmount에 실행됩니다.`);
        }
    }, [name]);

    return (
        <div>
            이름:<input type="text" onChange={handleName}/><br/>
            이름:{name}
        </div>
    )
}

export default HookEffect;

특정 태그에 이름달기 useRef()

useRef(초기값)

const 사용할 이름 = useRef(null);

● 이벤트를 사용하다 보면 특정 태그에 접근해서 핸들링 하는 경우가 생긴다.
● arrow function에 event 매개변수를 이용해 자신 태그에는 접근할 수 있지만, 다른 태그는 핸들링 하기가 어렵다.
● 이런경우 useRef() 훅을 이용해서 특정태그에 이름을 지정하고 핸들링 할 수 있다.
useRef는 초기값을 객체로( {current:vlue} ) 저장하기때문에 변수명.current로 현재태그에 접근 할 수있다.
const HookRef = () => {
    //useState
    const [form, setForm] = useState({data: '', result: '' });
    //useRef
    const inputTag = useRef(null);
    //인풋핸들링
    const handleChange = (e) => {
        setForm( {data :e.target.value} ); //인풋값이 변할때마다 data변수 변화
    }
    
    //버튼핸들링 - 클릭시 state는 변경하고, input태그에 포커스
    const handleClick = (e) => {
        setForm( {data: '', result: form.data})
        //useRef의사용 - current로 ref의 현재태그에 접근가능
        inputTag.current.focus()
    }

    return (
        <div>
            할일: <input type="text" value={form.data} onChange={handleChange} ref={inputTag} />
            <button type="button" onClick={handleClick}>등록하기</button>

            <br/>
            결과: {form.result}

        </div>
    )
}

export default HookRef;

외부에서 state사용하기 useReducer()

  • useReducer는 state와 비슷하다.
  • useReducer는 외부에서 state를 관리할 수 있게 해준다.
  • 리듀서함수를 외부로 export하게 되면 로직을 분리할 수 있다. (재사용이 가능해짐)

Reducer 함수의 모형

const 리듀서함수명 = (state값, 리듀서action함수로 전달하는 상태값) => {
	//초기값을 action 상태에 따라서 변경
	return state값
}

Reducer 함수의 사용 예시

import { useReducer } from "react";

//컴포넌트 외부에 선언
//리듀서(상태제어)는 (현재state, 리듀서action함수로 전달하는 상태값) 를 받습니다.
const myReducer = (state, action) => {

    if(action.type === 'increase') {
        state = { value: state.value+1 }
    } else if(action.type === 'decrease') {
        state = { value: state.value-1 }
    } else if(action.type === 'reset'){
        state = { value : 0}
    } 

    return state
}

const HookReducer = () => {

    //state에서 만들었던 증가,감소 리듀서 적용하기
    //1. const[state값 , 리듀서실행함수] useReducer( 리듀서, state초기값)
    const [state, func] = useReducer(myReducer, {value:0 } )

    const handleIncrease = () => {
        func({type: 'increase'});
    }

    return (
        <div>
            <button type="button" onClick={ handleIncrease }>증가</button>
            <button type="button" onClick={ () => func({type: 'decrease'}) }>감소</button>
            <button type="button" onClick={ () => func({type: 'reset'}) }>초기화</button>
            <br/>
            현재카운트 {state.value}
        </div>
    )
}

export default HookReducer;

UseState와 UseReducer의 비교

  1. useState, useReducer 모두 상태를 관리하는 훅이다.
  2. useState는 관리할 상태가 간단할 때 일반적으로 사용하면 좋다.
  3. 반면 관리할 상태가 여러 개이고, 서로가 의존하고 있으며 상태 조작할 동작이 여러 개일 때는 useReducer가 권장
  4. 반드시 useReducer를 써야하는 것은 아니다. useState가 대체할 수 있기 때문이다.

※ 훅의 종류는 이뿐이 아니고 굉장히 많다.

컴포넌트의 성능을 최적화하는 훅

  • useMemo와 useCallback 이 있다.
728x90

'Programming > React' 카테고리의 다른 글

[REACT] React 라우터  (0) 2024.05.14
[REACT] React에 CSS 적용하기  (0) 2024.05.14
[REACT] 컴포넌트 반복  (0) 2024.05.14
[REACT] React Event  (0) 2024.05.14
[REACT] STATE  (0) 2024.05.14