[리액트] 기초 개념 Hook

AnSuebin·2022년 8월 17일
0

[리액트] 개념 정리

목록 보기
5/13

8. 리액트 훅

1) 리액트 훅이란

  • 컴포넌트에 기능을 추가할 때 사용하는 함수
  • 예로 컴포넌트에 상태값을 추가, 자식요소에 접근하는 등의 기능 추가
  • 과거는 클래스형 컴포넌트 사용

2) useState : 상태값 관리 Hook

  • 리엑트는 효율적으로 렌더링 하기 위하여 여러가지 상대값 변경 요청을 배치로 처리한다. 따라서 onClick 함수가 호출되어도 setCount는 두번 작성하였지만, count값은 1씩만 증가하고 console.log('render called') 로그는 한번만 출력된다.
  • 상태값 변경 요청을 왜 비동기 이면서 배치로 처리할까? 만약에 동기로 처리한다면 상태값 변경 함수가 호출될 때마다 화면을 다시 그리기 때문에 성능 이슈가 생길 수 있다.
  • 이러한 이슈를 줄이기 위해 상태값 변경 함수에는 함수를 입력한다
    • 함수로 입력하면 처리되기 직전의 상태값을 매개변수로 받기 때문에 원하는 대로 동작한다.
    • onClick 이벤트 핸들러는 리액트 내부에서 관리되는 리액트 요소에 입력이 되어 있기 때문에 배치로 처리가 된다.
    • 리엑트 내부에서 관리하지 않는 외부에서 호출을 하는 경우에는 배치로 동작하지 않는다. 즉 그러한 경우에는 상태값 변경 함수를 호출할 때마다 렌더링이 발생한다.
import React, { useState, useEffect } from 'react';

export default function App() {
    const [count, setCount] = useState(0);

    function onClick() {
        setCount(v => v + 1);
        setCount(v => v + 1);
    }

    console.log('render called');

    return (
        <div>
            <h2>{count}</h2>
            <button onClick={onClick}>증가</button>
        </div>
    );
}

3) useEffect: 부수 효과 처리 Hook

  • 부수 효과란 외부의 상태를 변경하는 것을 말한다.
  • 서버 API호출, 이벤트 핸들러 등록/해제 등의 부수 효과를 처리할 때 사용한다.
  • 컴포넌트 렌더링 중에 부수 효과를 발생 시키는 것은 프로그램의 복잡도를 크게 증가 시키고 유닛 테스트를 작성하기 힘들어지는 등 순수 함수가 가지는 여러 장점을 포기하는 것이다.
    • useEffect 함수의 첫 번째 매개변수로 함수를 입력한다.
    • 이 함수는 컴포넌트가 렌더링된 후에 호출이 된다.
    • 렌더링 결과가 실제 돔에 반영되고나서 비동기로 호출이 되는 것이다.
    • 이 첫 번째 매개변수 함수를 부수 효과 함수 라고 부른다
export default function App() {
    const [count, setCount] = useState(0);

    useEffect(() => {
        document.title = `업데이트 횟수: ${count}`;
    });

    return <button onClick={() => setCount(count + 1)}>increase</button>;
}

📍 동기호출

요청에 대한 결과가 동시에 일어난다.

📍 비동기호출

요청에 대한 결과가 동시에 일어나지 않고 요청을 한번에 다받고 이벤트가 준비 되었을 때 응답을 나중에 이루어진다.

4) useEffect 와 의존성 배열

  • 부수효과 함수는 렌더링이 끝나고 호출이 된다. 그런데 만약 렌더링이 자주 발생한다면 그 때마다 API를 호출하는 것은 비효율적이다.
  • 이럴 때는 두 번째 매개변수에 배열을 입력할 수 있다. 이 배열은 의존성 배열이다. 이 배열의 값이 변경될 때만 부수효과 함수가 실행된다.
  • 만약 두 번째 매개변수에 빈 배열을 입력하면 부수 효과 함수는 컴포넌트가 마운트된 이후에 한 번만 호출될 것이다.
import React, { useState, useEffect } from 'react';

export default function Profile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    getUserApi(userId).then(data => setUser(data));
  }, [userId]);

  return (
    <div>
    {!user && <p>사용자 정보를 가져오는 중...</p>}
    {user && (
      <>
        <p>{`name is ${user.name}`}</p>
        <p>{`age is ${user.age}`}</p>
      </>
    )}
    </div>
  );
}

const USER1 = { name: 'mike', age: 23 };
const USER2 = { name: 'jane', age: 31 };

function getUserApi(userId) {
  return new Promise(result => {
    setTimeout(() => {
      result(userId % 2 ? USER1 : USER2);
    }, 500);
  });
}

5) 의존성 배열에 어떤 값을 입력해야 할까

  • 부수 효과 함수에서 사용한 변수를 잘 봐야 한다.
    컴포넌트의 상태값, 속성값, 컴포넌트 내부에서 정의된 지역변수, 지역함수 같은 것들은 모두 의존성 배열에 작성을 해줘야 한다.
  • getUserApi는 외부에 있는 함수이기 때문에 입력하지 않아도 된다.
    userId는 속성값이기 때문에 입력을 해줘야 한다.
  • setUser 상태값 변경 함수는 조금 특별한데, 이 함수는 값이 변경되지 않는다는 것이 보장된다. 그래서 상태값 변경함수는 예외적으로 의존성 배열에 입력하지 않아도 된다.
  • 의존성 배열은 꼭 필요한 경우에만 입력하는 게 좋다. 예를 들어 새로운 상태값을 추가한 다음에 부수 효과 함수에서 사용을 하면 매번 사용한 변수를 의존성 배열에 추가해야 하는 번거로움이 생긴다.
  • 의존성 배열을 잘못 입력하면서 많은 버그가 발생하니 주의하자.

6) 부수 효과 함수가 반환하는 값

export default function WidthPrinter() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const onResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', onResize); // 이벤트 리스너 등록

    return () => {
      window.removeEventListener('resize', onResize); // 이벤트 리스너 해제
    };
  }, []);

  return <div>{`width is ${width}`}</div>;
}
  • 부수 효과 함수에서 반환하는 함수는 다음 부수 효과 함수가 호출되기 직전에 호출된다. 또는 컴포넌트가 언마운트 되기 직전에 마지막으로 호출된다.
  • 의존성 배열로 빈 배열을 입력하면 컴포넌트가 생성될 때만 부수 효과 함수가 호출되고, 부수 효과 함수가 반환하는 함수는 컴포넌트가 사라지기 직전에 한 번만 실행된다.
profile
고객에게 명료한 의미를 전달하고, 명료한 코드를 통해 생산성 향상에 기여하고자 노력합니다.

0개의 댓글