리액트 공식 문서 정리 - Hook 소개, useState(자세히), useEffect 맛보기, Hook 규칙

Jessie H·2022년 9월 8일
0

react

목록 보기
11/13
post-thumbnail

React Hook

  • 리액트 16.8 버전부터 추가됨
  • 함수 컴포넌트에서도 클래스 컴포넌트처럼 상태 관리 등의 여러 기능을 사용할 수 있게 됨
  • 클래스 컴포넌트에서는 사용 x
  • Hook은 계층의 변화 없이 상태 관련 로직을 재사용할 수 있도록 함
  • 컴포넌트를 독립적이고 재사용할 수 있게 해줌
  • this를 사용할 필요가 없어 훨씬 더 직관적
  • Hook을 통해 서로 비슷한 역할의 작은 함수 묶음으로 컴포넌트 나누기 가능

자주 쓰이는 Hook

useState(state Hook)

  • 함수 컴포넌트에서 React state와 생명주기 기능(lifecycle features)을 “연동(hook into)“할 수 있게 해주는 함수
  • 함수 컴포넌트는 this를 가질 수 없기 때문에 this.state 사용x
  • useState hook을 함수 컴포넌트에 직접 호출
  • state 변수는 일반 함수 내의 변수와 달리 함수가 끝날 때 사라지지 않음
  • React는 해당 변수를 리렌더링할 때 기억하고, 가장 최근에 갱신된 값을 제공
  • 따라서 setState 함수를 통해 state을 값을 갱신할 경우 state가 직접 수정되는 것이 아니라 새로운 값으로 대체되는 것
    (덮어쓰기 같이!!)
  • useState 시작방법: const [state변수이름, set + state 변수이름] = useState(초기값);
    (위의 []의미는 배열 구조 분해 문법(구조 분해 할당)과 연관)
  • state 변수명은 맘대로 작명 가능
  • state를 업데이트하는 함수는 set + state변수이름 이름으로 작명
import React, {useState} from "react";

const [count, setCount] = useState(0);

//count는 state 변수명, setCount는 state를 업데이트하는 함수
  • 사용법: 중괄호로 감싸고 state변수명을 직접 입력
<p>It is {count}</p>
  • state는 변수는 여러 개 선언 가능
 const [age, setAge] = useState(42);
 const [fruit, setFruit] = useState('banana');
  • state의 초기값으로 배열, 객체, 함수도 가능
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);

useEffect

useEffect 보기 전 알면 좋은 것들

side effect를 이해하려면 먼저 자바스크립트의 "순수 함수" 개념에 대한 이해가 필요

pure function 순수 함수

  • 입력값과 반환값이 일정한 함수
    (동일한 입력이 주어지면 항상 동일한 출력을 반환)
  • side effect를 발생시키지 않는 함수 -> 외부 상태를 변경하지 않는 함수

side effect: 외부와의 상호작용

  • 파일 읽기 또는 파일 쓰기
  • 네트워크 요청하기(API 호출, 파일 다운로드 등)
  • 전역 상태에서 읽기(예: 전역 변수, 부모 클로저의 매개변수 등)
  • 예외 던지기/차단하기
  • 웹 애플리케이션의 경우 DOM 개체 및 메서드 사용
  • 콘솔에 메시지 로깅

side effect 출처: https://dev.to/ruizb/side-effects-21fc

리액트에서 말하는 컴포넌트의 side effects 구체적 예시

그래서 useEffect가 뭔데?

  • 함수 컴포넌트에서 "side Effect" 기능을 사용할 수 있게 하는 hook
  • React class의 componentDidMount, componentDidUpdate, componentWillUnmount 합친 것
  • 렌더링 이후 실행됨
  • side effect 기능 관련 코드들을 한군데에 모아서 작성 가능

useEffect 설명은 다음 글에서 더 자세히 다룰 예정!

Hook 사용 규칙

규칙 1: early return 실행 전 + 최상위 레벨에서만 사용

  • 조건문, 반복문, 중첩된 함수 내에서 사용x
  • 동일한 순서로 hook 호출 가능해짐 -> state 상태 올바르게 유지 가능
  • 예시로 보기
function exFunc() {
  const [isClicked, setIsClicked] = useState(false);
  
  useEffect(() => {
    console.log("isClicked changed!");
  }, [isClicked]);

  useEffect(() => {
    console.log("exFunc first rendering");
  }, []);
  
  return <button onClick={() => setIsClicked(!isClicked)}>click</button>
}

이 exFunc 함수 컴포넌트 첫 렌더링 후 버튼을 클릭 시 렌더링 되는 과정은 다음과 같다

//첫번째 렌더링
useState(false) //isClicked가 false으로 초기화
useEffect(...console.log("isClicked changed!")) //console에 "isClicked changed!" 출력
useEffect(...console.log("exFunc first rendering)) //console에 "exFunc first rendering" 출력

//hook 순서: useState -> useEffect -> useEffect로 기억

//버튼 1회 클릭 후
useState(1) //isClicked가 true로 초기화
useEffect(...console.log("isClicked changed!")) //console에 "isClicked changed!" 출력
useEffect(...console.log("exFunc first rendering)) //console에 "exFunc first rendering" 출력

그럼 두번째 useEffect를 조건문으로 감싼 exFunc2로 규칙을 깨면 어떤 현상이 발생하는지 알아보자

function exFunc2() {
  const [isClicked, setIsClicked] = useState(false);
  
  if (isClicked < 1) {
    useEffect(() => {
      console.log("isClicked changed!");
    }, [isClicked]);
 }
 
  useEffect(() => {
    console.log("exFunc first rendering");
  }, []);
  
  return <button onClick={() => setIsClicked(!isClicked)}>click</button>
}

이 컴포넌트가 첫 렌더링 한 후 버튼을 클릭하면 어떻게 될까?

//첫번째 렌더링
useState(0) //clickedNum이 0으로 초기화
useEffect(...console.log("isClicked changed!")) //console에 "isClicked changed!" 출력
useEffect(...console.log("exFunc first rendering)) //console에 "exFunc first rendering" 출력

//hook 순서: useState -> useEffect -> useEffect로 기억

//버튼 1회 클릭 후
useState(1) //clickedNum이 1로 초기화
XXX useEffect(...console.log("button is clicked!")) XXX //isClicked가 1이 되었으므로 pass!
useEffect(...console.log("exFunc first rendering)) //기억한 hook의 순서가 달라져 실행 실패

예시 참고: https://velog.io/@humonnom/Hook-Hook%EC%9D%98-%EA%B7%9C%EC%B9%991

hook순서가 기억된 대로 실행을 하지 않으면 오류가 나기 때문에 조건문, 반복문, 중첩 함수 등 내부에 hook을 사용하면 안된다.
useEffect에 조건문을 써야할 때가 있는데 그러면 useEffect 안에서 조건문을 사용하면 된다.


규칙 2: 리액트 함수 내에서만 호출

  • 함수 컴포넌트 안에서 호출
  • custom hook에서 호출(custom hook은 따로 다룰 예정)
  • 순수 자바스크립트 함수에서 호출x
profile
코딩 공부 기록장

0개의 댓글