[소플 : React] 7. 훅

I'm Your Cho-i·2022년 11월 14일
0

React

목록 보기
12/13
post-thumbnail

📌Hook

기존 클래스 컴퍼넌트에서 사용하던 생명주기를 대체

리액트의 state와 생명주기 기능에 갈고리를 걸어 원하는 시점에 정해진 함수를 실행되도록 만든 것

훅의 이름은 모두 use로 시작.

📌useState

클래스 컴포넌트처럼 state를 사용하고 싶으면 useState()훅을 사용

const [변수명, set함수명] = useState(초깃값);
import React, { useState } from 'react';

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

버튼이 눌렸을 때 setCount()함수를 호출해서 카운트를 1 증가.
count의 값이 변경되면 컴포넌트가 재렌더링되면서 화면에 새로운 카운트 값이 표시.

대괄호 의미?

const [fruit, setFruit] = useState('banana');

위 자바스크립트 문법은 "배열 구조 분해".
즉, useState를 사용하면 fruit라는 첫 번째 값과 setFruit라는 두 번째 값을 반환.
아래의 코드와 같은 효과를 냄.

var fruitStateVariable = useState('banana'); // 두 개의 아이템이 있는 쌍을 반환
var fruit = fruitStateVariable[0]; // 첫 번째 아이템
var setFruit = fruitStateVariable[1]; // 두 번째 아이템

useState를 이용하여 변수를 선언하면 2개의 아이템 쌍이 들어있는 배열로 만들어짐.
첫 번째 아이템은 현재 변수를 의미, 두 번째 아이템은 해당 변수를 갱신해주는 함수.

// this.setState({ fruit: 'orange' })와 같은 효과를 냅니다.
setFruit('orange');

📌useEffect

리액트 함수 컴포넌트에서 사이드 이펙트를 실행할 수 있도록 해주는 훅
클래스 컴포넌트에서 제공하는 생명주기 함수인 componentDidMount() componentDidupdat() componentWillUnmount()와 동일한 기능을 하나로 통합해서 제공.

  • 뭔가가 바뀌면 어떤 동작을 자동으로 실행하기 위해 사용
  • 인자
    • 인라인 콜백함수: 의존성 리스트에 있는 항목 중의 하나가 업데이트 되면 실행시킬 동작
    • 의존성 리스트: 이 리스트에 있는 요소가 업데이트되면 콜백함수를 다시 작동시킨다.
useEffect(이펙트 함수, 의존성 배열);

첫 번째 파라미터로는 이펙트 함수가 들어가고, 두 번째 파라미터로는 의존성 배열이 들어감.
의존성 배열은 배열 안에 있는 변수 중에 하나라도 값이 변경되었을 때 이펙트 함수가 실행.

 useEffect(() => {
    document.title = `You clicked ${count} times`;
 });

위 처럼 의존성 배열 없이 useEffect()를 사용하면 리액트는 DOM이 변경된 이후에 해당 이펙트 함수를 실행하라는 의미

componentDidMount() componentDidupdat() 와 동일한 역할

useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
});

useEffect()에서 리턴하는 함수는 컴포넌트가 마운트 해제될 때 호출
componentWillUnmount()와 동일한 역할

useEffect(() => {
  //컴포넌트가 마운트 된 이후
  //의존성 배열에 있는 변수들 중 하나라도 값이 변경되었을 때 실행됨
  //의존성 배열에 빈 배열([])을 넣으면 마운트와 언마운트시에 단 한 번씩만 실행됨
  //의존성 배열 생략 시 컴포넌트 업데이트 시마다 실행됨
  return () => {
  	//컴포넌트가 마운트 해제되기 전에 실행됨
  }
}, [의존성 변수1, 의존성 변수2, ...]);

📌 useMemo

의존성 배열에 들어있는 변수가 변했을 경우에만 새로 create 함수를 호출하여 결괏값 반환.
렌더링이 일어나는 동안 실행됨

const memoizedValue = useMemo(
  () => {
    //연산량이 높은 작업을 수행하여 결과 반환
    return computeExpensiveValue(의존성 변수1, 의존성 변수2);
  },[의존성 변수1, 의존성 변수2]
);
  • useCallback은 원하는 타이밍에 실행시킬 함수를 만드는데 사용
  • 그에 비해 useMemo는 원하는 값을 업데이트하기 위해 사용

📌 useCallback

useMemo()와 유사한 역할. 값이 아닌 함수를 반환

  • 원하는 타이밍에 호출시킬 함수를 만들기 위해 사용(함수가 반환됨)
  • 인자
    • 인라인 콜백함수: 원하는 타이밍에 동작시킬 동작
    • 의존성 리스트: 의존성에 포함된 요소가 업데이트 될 경우, 반환되는 함수도 갱신됨
const memoizedCallback = useCallback(
  () => {
    doSomething(의존성 변수1, 의존성 변수2);
  },[의존성 변수1, 의존성 변수2]
);

📌 useRef

변경 가능한 .current라는 속성을 가진 하나의 상자

const refContainer = useRef(초깃값);

React에서 DOM 엘리먼트의 주소값이 필요할 때 사용할 수 있다.

  • focus
  • text selection
  • media playback
  • 애니메이션 적용
  • d3.js, greensock 등 DOM 기반 라이브러리 활용
import { useRef } from 'react';
/* 1. 사용할 수 있도록 훅을 불러온다. */

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  /* 2. inputEl은 특정 엘리먼트의 주소값을 담는 변수가 된다. */
  
  const onButtonClick = () => {
    inputEl.current.focus();
    /* 4. 해당 함수가 실행되면, inputEl이 가지고 있는 주소값(input)이 focus된다. */
  };
  
  return (
    <>
      <input ref={inputEl} type="text" />
    /* 3. 특정 태그에 ref 속성을 붙이고 미리 할당했던 useRef 객체를 넣으면, 
    해당 태그의 주소값을 inputEl이라는 변수가 가지고 있게 된다. */
      <button onClick={onButtonClick}>Focus the input</button>
    </>);
}

ex) 영상 플레이/정지 등을 영상 제어하고 싶을 때

import { useRef } from "react";

export default function App() {
  const videoRef = useRef(null);
  /* 1. useRef를 변수에 할당하고 */

  const playVideo = () => {
    videoRef.current.play();
    console.log(videoRef.current);
    /* 3. 버튼 클릭으로 비디오 재생을 제어하거나 */
  };

  const pauseVideo = () => {
    videoRef.current.pause();
    videoRef.current.remove();
    /* 4. 비디오 재생을 멈출 수도 있다. */
  };

  return (
    <div className="App">
      <div>
        <button onClick={playVideo}>Play</button>
        <button onClick={pauseVideo}>Pause</button>
      </div>
      <video ref={videoRef} width="320" height="240" controls>
        /* 2. 비디오 태그의 ref 속성에 해당 변수를 할당하면 */
        <source
          type="video/mp4"
          src="https://player.vimeo.com/external/544643152.sd.mp4?s=7dbf132a4774254dde51f4f9baabbd92f6941282&profile_id=165"
        />
      </video>
    </div>
  );
}

📎 요약

  • 훅이란?
    • 리액트의 state와 생명주기 기능에 갈고리를 걸어 원하는 시점에 정해진 함수를 실행되도록 만든 것
  • useState()
    • state를 사용하기 위한 훅
    • 함수 컴포넌트에서는 기본적으로 state라는 것을 제공하지 않음
    • 클래스 컴포넌트처럼 state를 사용하고 싶으면 useState()훅을 사용해야 함
    • 사용법
      • const [변수명, set함수명] = useState(초깃값);
      • 변수 각각에 대해 set 함수가 따로 존재함
  • useEffect()
    • 사이드 이펙트를 수행하기 위한 훅
    • 사이드 이펙트란 서버에서 데이터를 받아오거나 수동으로 DOM을 변경하는 등의 작업
    • useEffect() 훅만으로 클래스 컴포넌트의 생명주기 함수들과 동일한 기능을 수행할 수 있음
    • 사용법
      • useEffect(이펙트 함수, 의존성 배열);
      • 의존성 배열 안에 있는 변수 중에 하나라도 값이 변경되었을 때 이펙트 함수가 실행됨
      • 의존성 배열에 빈 배열([])을 넣으면 마운트와 언마운트시에 단 한 번씩만 실행됨
      • 의존성 배열 생략 시 컴포넌트가 업데이트될 때마다 호출됨
      • 선언된 컴포넌트의 props와 state에 접근할 수 있음
      • useEffect()에서 리턴하는 함수는 컴포넌트 마운트가 해제될 때 호출됨
  • useMemo()
    • Memoized value를 리턴하는 훅
    • 연산량이 높은 작업이 매번 렌더링될 때마다 반복되는 것을 피하기 위해 사용
    • 렌더링이 일어나는 동안 실행되므로 렌더링이 일어나는 동안 실행되서는 안될 작업을 useMemo()에 넣으면 안됨
    • 사용법
      • const memoizedValue = useMemo(값 생성 함수, 의존성 배열);
      • 의존성 배열에 들어있는 변수가 변했을 경우에만 새로 값 생성 함수를 호출하여 결괏값을 반환함
      • 그렇지 않은 경우에는 기존 함수의 결괏값을 그대로 반환함
      • 의존성 배열을 넣지 않을 경우 렌더링이 일어날 때마다 매번 값 생성 함수가 실행되므로 의미가 없음
  • useCallback()
    • useMemo() 훅과 유사하지만 값이 아닌 함수를 반환한다는 점이 다름
    • 컴포넌트 내에 함수를 정의하면 매번 렌더링이 일어날 때마다 함수가 새로 정의되므로 useCallback() 훅을 사용하여 불필요한 함수 재정의 작업을 없애는 것
    • 사용법
      • const memoizedCallback = useCallback(콜백 함수, 의존성 배열);
      • 의존성 배열에 들어있는 변수가 변했을 경우에만 콜백 함수를 다시 정의해서 리턴함
  • useRef()
    • 레퍼런스를 사용하기 위한 훅
    • 레퍼런스란 특정 컴포넌트에 접근할 수 있는 객체를 의미
    • 매번 렌더링될 때마다 항상 같은 레퍼런스 객체를 반환
    • 사용법
      • const refContainer = useRef(초깃값);
      • .current 라는 속성을 통해서 접근

훅의 규칙

  • 무조건 최상위 레벨에서만 호출해야 함
    • 반복문이나 조건문 또는 중첩된 함수들 안에서 훅을 호출하면 안 됨
    • 컴포넌트가 렌더링될 때마다 매번 같은 순서로 호출되어야 함
  • 리액트 함수 컴포넌트에서만 훅을 호출해야 함
    • 훅은 리액트 함수 컴포넌트에서 호출하거나 직접 만든 커스텀 훅에서만 호출할 수 있음

커스텀 훅

  • 이름이 use로 시작하고 내부에서 다른 훅을 호출하는 단순한 자바스크립트 함수
  • 파라미터로 무엇을 받을지, 어떤 것을 리턴해야 할지를 개발자가 직접 정할 수 있음
  • 중복되는 로직을 커스텀 훅으로 추출하여 재사용성을 높이기
  • 이름이 use로 시작하지 않으면 특정 함수의 내부에서 훅을 호출하는지를 알 수 없기 때문에 훅의 규칙위반 여부를 자동으로 확인할 수 없음

💻 소플의 처음만난 리액트

profile
https://github.com/Cho-i

0개의 댓글