프론트엔드/React

[ React ] [Chapter 10] Hook의 기초 알기

IT마스터되자 2020. 11. 21. 22:29
728x90

Hook

 

챕터 8 useState 편에서 훅에 대해 잠깐 설명 했습니다.이 챕터에서는 훅의 기초를 알아가는 시간을 가지겠습니다.Hook(훅)
컴포넌트에 기능을 추가할 때 사용 하는 함수이다.
예를 들어 컴포넌트에 상태값 추가나 자식 요소에 접근 하거나 할 때 사용하죠리액트 16.8버전 이후 부터 기능이 추가가 되었습니다.
그 전에는 클래스형 컴포넌트를 사용 했습니다. 그러나 이제 훅이 나오면서 많은 개발자들이 함수형 컴포넌트로 바꾸기 시작했습니다.
클래스형 컴포넌트보다 장점이 많고, 리액트 팀에서도 훅에 많은 집중을 하고 있습니다.
그래서 리액트 훅으로 작성 하는것을 추천한다.
리액트에서 제공하는 대표적인 두 가지 기능이 있다.

1.useState
상태값 추가

 

2.useEffect
부수적인 기능들 처리 할 때 쓰인다. 서버 API 호출이나  이벤트 핸들러 처리 등등

useState에 대해서는 챕터 8을 참고해주세요.

useEffect

 

큰 이유가 없다면 모든 부수효과 기능 처리는 useEffect로 처리하는게 좋다.

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

function App() {
	const [ count, setCount ] = useState(0);
    useEffect(() => {
    	document.title = '업데이트 : ${count}';
    });
    return <button onClick={() => setCount(count + 1)}>plus</button>;
}

useEffect의 사용법은 이와 같은데

첫번째 매개변수로 함수를 입력 하면 저 함수는 컴포넌트가 랜더링 된 후에 호출이 된다.
렌더링 결과가 실제 DOM에 반영되고, 비동기로 호출이 된다.

버튼을 클릭 할 때마다 setCount에 의해 count는 증가 해서 state가 변화가 일어나니 컴포넌트는 랜더링이 될거고
useEffect이 실행이 된다.

저 함수를 부수효과 함수라고 불린다.


좀 실제 같은 환경으로 예시를 들어보자

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

function App() {
  return (
    <div>
      <MemberComponent memberIdx={1}/>
    </div>
  );
}

function MemberComponent({ memberIdx }) {
  const [ member, setMember ] = useState(null);
  useEffect(() => {
    serverApi(memberIdx).then(it => setMember(it));
  }, [memberIdx]);
  return (
    <div>
      {!member && <p>고객 정보...</p>}
      {member && (
        <Fragment>
          <p>{`id : ${member.id}`}</p>
          <p>{`pwd : ${member.pwd}`}</p>
        </Fragment>
      )}
    </div>
  );
}

const MEMBER01 = { id : 'test01Id', pwd:'123' };
const MEMBER02 = { id : 'test02Id', pwd:'124' };
function serverApi(memberIdx) {
  return new Promise(res => {
    setTimeout(() => {
      res(memberIdx % 2 ? MEMBER01 : MEMBER02);
    }, 600)
  })
}

export default App;

MemberComponent 컴포넌트가 있는데 이거는 멤버를 랜더링 해주는 컴포넌트이다. App에서 memberIdx 를 속성 값을 던져주면 MemberComponent는 memberIdx를 속성 값으로 받아서 api를 호출 하고 해당 멤버 정보를 가져온 다음 멤버 상태값을 변경 해주는 기능을 하고 있는데.

이 기능을 useEffect에서 정의 하고 있다.

코드 설명을 하자면 useEffect 에 알지 못하는 두번째 매개변수가 있다.
첫번째 매개 변수라면 처리하는 함수라고 이전에 배웠는데 두번째 매개변수는 배운적이 없다.

상황으로 예를 들어보자
만약 랜더링이 자주 발생 한다면 useEffect는 그만큼 호출이 될거고 useEffect 호출 된 만큼 api도 호출을 할거다
그러면 비효율 적이기 때문에 useEffect 두번째 매개변수에 배열을 입력해 관리 할 수 있다.

저 memberIdx 배열은 의존성 배열이라고 부르는데 이 배열에 있는 값이 변경 될 때만 부수효과 함수(useEffect)가 실행 된다는 말이다.


그러면 저 의존성 배열에 어떤 값들을 입력해야 할까?

부수효과 함수에서 사용한 변수를 잘 봐야 하는데, 컴포넌트 상태값이나 속성값
또는 컴포넌트 내부에서 정의된 지역 변수나 지역 함수 같은 것들을 모두 의존성 배열에 작성 해줘야 합니다.

그리고 의존성 배열은 꼭 필요한 상황에만 입력 하는것이 좋다.

예를 들어 의존성 배열을 사용 하는데 새로운 상태값을 추가하고 useEffect 함수내에 사용 되었다면 꼭 의존성 배열에 추가 해야 하는 번거로움이 생깁니다.

또 한, 의존성 배열 때문에 useEffect 많은 버그가 생깁니다. 잘못 입력할 경우에요.

Tip 인듯 아닌듯
의존성 배열에 아무것도 안하면 빈 값 말고 빈 배열 [] 을 넣으면 컴포넌트가 생성 될 때만 호출이 됩니다.


useEffect 반환 값

useEffect(() => {
    serverApi(memberIdx).then(it => setMember(it));
    return () => {
      console.log('return! ');
    };
  }, [memberIdx]);

전 코드에서 return () => { 콘솔찍어 } 추가 해보면 첫 랜더링 때는 콘솔이 안찍히는걸 알수 있다.

이 리턴 값은 다음 부수효과 함수가 호출 되기 진적에 호출이 된다.
또는 컴포넌트가 사라지기 직전에(unmount) 마지막으로 호출 됩니다.

이러한 부수효과  함수가 반환한 이러한 함수는 컴포넌트가 unmount 되기 전에 적어도 한번은 호출 된다는 것이 보장이 됩니다.

이렇게 훅에 대해 기초와 훅에서 많이 사용하는 기능을 배웠습니다
다음은 커스텀 훅 만들기로 뵙겠습니다.

훅 사용 시 지켜야 할 규칙

 

1. 하나의 컴포넌트에서 훅을 호출 하는 순서는 항상 같아야합니다.

2. 훅은 함수형 컴포넌트 또는 커스텀 훅 안에서만 호출 되어야 합니다.

이규칙을 지켜야 리액트가 각 훅의 상태를 제대로 기억할 수 있습니다.

2번에 의해서 클래스형 컴포넌트의 메서드 뿐만 아니라 기타 일반 함수에서도 사용할 수없습니다.
왜냐하면 사실 훅은 함수형 컴포넌트를 위한 기능이라고 보면 됩니다.


1번째 규칙의 예

function ItJava() {
	const [ value, setValue ] = useState(0);
    if(value === 0) {
    	const [ val1, setVal1 ] = useState(0);
    } else {
    	const [ val1, setVal1 ] = useState(0);
        const [ val2, setVal2 ] = useState(0);
    }
}

훅은 항상 같은 순서로 호출이 되어야 하기 때문에 이렇게 IF문 안에서 훅을 사용 하면 어쩔 때는 한번 사용 했다가, 어쩔 때는 두번 사용 했다가 그렇게 되어서 안됩니다.

 

function ItJava() {
    for(lef 1=0; 1<value; 1++) {
    	const [ val1, setVal1 ] = useState(0);
    }
}

for문 안에서도 사용하면 안됩니다. value에 따라서 useState 사용하는 횟수가 달라지기 때문이다.

 

function ItJava() {
    function func01() {
    	const [ val1, setVal1 ] = useState(0);
    }
}

함수안에서 훅을 호출해도 안됩니다. func01 함수가 항상 호출 된다는 보장이 없기 때문이다.

 

function ItJava() {
	if(isOk) {
    	return null;
    }
    const [ val1, setVal1 ] = useState(0);
	return (
    <div>
    </div>
  );
}

이럴 경우에도 안됩니다. isok에 의해 호출이 될수도 안될 수도 있기 때문이다.

   관련 글

 

저의 글을 읽어 주셔서 감사합니다. 오늘도 즐거운 하루 보내세요.

저의 글이 조금이나마 도움이 되셨다면 로그인이 필요 없는 공감♥ 한번 꾸욱 눌러주세요 하하~

728x90