[React] Hook

열심히하시는개발자·2021년 2월 12일
0
post-thumbnail

1️⃣ Hook이란?

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



2️⃣ State Hook

import React, { useState } from 'react';

function Example() {
  // "count"라는 새 상태 변수를 선언합니다
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
  • useState가 Hook이라는 녀석인데 Hook을 호출해 함수 컴포넌트안에 state를 추가한다.
  • 이 state는 컴포넌트가 다시 렌더링 되어도 그대로 유지되고 useState는 현재의 state값과 이 값을 업데이트하는 함수를 쌍으로 제공한다.
  • 언뜻 보면 class의 this.setState와 거의 유사하지만, 이전 state와 새로운 state를 합치지 않는다는 차이점이 있다.



2️⃣➖1️⃣ 여러 state 변수 선언

function ExampleWithManyStates() {
  // 상태 변수를 여러 개 선언했습니다!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}
  • 구조 분해(destructing)문법은 useState로 호출된 state변수들을 다른 변수명으로 할당할 수 있게 해준다.
  • React는 매번 렌더링 할 때 useState가 사용된 순서대로 실행 된다.
import React, { useState } from 'react';

function Example() {
  // 새로운 state 변수를 선언하고, 이것을 count라 부르겠습니다.
  const [count, setCount] = useState(0);

useState를 호출하는 것은 무얼을 하는 걸까?

  • state변수를 선언할 수 있다.
  • 일반 변수는 함수가 끝날 때 사라지지만, state변수는 React에 의해 사라지지 않는다.

useState의 인자로 무엇을 넘겨주어야 할까?

  • useState의 인자로 넘겨주는 값은 state의 초기값 이다.
  • 함수 컴포넌트의 state는 클래스와 달리 객체일 필요가 없고, 숫자와 문자 타입을 가질 수 있다.

useState는 무엇을 반환할까?

  • state변수, 해당 변수를 갱신할 수 있는 함수 이 두가지를 반환한다.
  • 그래서 const [count, setCount] = useState()라고 쓰는 이유이다.


3️⃣ Effect Hook이란 ?

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


3️⃣➖1️⃣ useEffect

useEffect(function);

useEffect(() => {}, [count]) // 의존성 배열 (배열 안에 담긴 값들을 추적, 그때 마다 업데이트)
  • 명령어 또는 어떤 effect를 발생하는 함수를 인자로 받는다.
  • 기본적으로 동작은 모든 렌더링이 완료된 후에 수행되지만, 어떤 값이 변경되었을 때만 실행되게 할 수도 있다.
  • 클래스형 컴포넌트와 비교한다면 useEffect는 여러가지 라이프 사이클이 합쳐진 형태로 설명 할 수 있다.

    componentDidMount (의존성 배열 : [])
    shouldComponentUpdate (의존성 배열 내에 해당 사항 없을 경우)
    componentDidUpdate (의존성 배열 자체가 없거나, 해당 사항이 있을 경우)
    componentWillUnmount



3️⃣➖2️⃣ useEffect의 동작

Render -> Effect Callback -> Clean Up

const Foo = () => {
  const [state, setState] = useState(0);

  console.log("render", state);

  useEffect(() => {
    console.log("useEffect Callback", state);
    return () => console.log("cleanUp", state);
  }, [state]);

  return <button onClick={() => setState(state + 1)}>하잉</button>;
};

export default Foo;
  • 함수 body => render
  • useEffect
    의존성 배열 : useEffect 내부에서 해당 값의 변화만 감지
    클린업 함수 : 구독/해제 등 다음 effect 전에 이번 effect의 내용을 정리해야 할 때 사용

기대한 동작 !

render, 0
useEffect Callback, 0
cleanUp, 0

// 클릭

render, 1
useEffect Callback, 1
cleanUp, 1

실제 동작 !

render, 0
useEffect Callback, 0

// 클릭

render, 1
cleanUp, 0
useEffect Callback, 1



의문점❗️

왜 다음 번 render보다 클린업 함수가 먼저 실행되나?

  • 렌더가 완료된 뒤에 effect를 실행하는 것이 더 나은 UX를 제공하기 때문이다.
  • effect가 실행될 시점에 렌더가 완료되어 있음을 보장할 수 있다.

왜 클린업 함수의 값은 예전 사이클의 값을 가져오는지?

  • 클로저는 자신이 생성될 시점에 환경을 기억하는 함수이다.
  • 클린업 함수가 클로저로서 생성될 시점은 이전 렌더 때, 즉 이전 환경을 기억하고 있는 것이 당연하다.

0개의 댓글