React - React Hooks

김서영·2024년 3월 5일
0

CS 스터디 - React

목록 보기
7/28

React Hooks


리액트의 함수형 컴포넌트에서 상태(state)및 생명주기(lifecycle) 기능을 사용할 수 있게 해주는 라이브러리

React Hooks 규칙

최상위에서만 Hook을 호출해야 한다.

  • 반복문이나 조건문 혹은 중첩된 함수 내에서 Hook을 호출할 수 없다.
    - 리액트 훅은 호출되는 순서에 의존하기 때문에 조건문이나 반복문 안에서 실행될 경우 해당 부분을 건너뛰는 일이 발생할 수도 있기 때문에 순서가 꼬여 버그가 발생할 수 있기 때문이다!!
    • 위의 규칙을 따른다면 useState와 useEffect가 여러번 호출되는 경우에도 Hook의 상태를 올바르게 유지할 수 있게 된다.

- 리액트 함수 내에서만 Hook을 호출해야 한다.

  • Hook은 일반적인 js함수에서는 호출할 수 없다.
  • 함수형 컴포넌트나 Custom Hook에서는 호출 가능하다.

React Hook 종류


useState

useState는 상태를 관리하는 훅

  • 함수형 컴포넌트 안에 state를 추가해 사용한다.
  • 현재 상태를 나타내는 state값과 이 상태를 변경하는 setState값을 한 쌍으로 작성한다.
  • state는 초기값을 설정할 수 있고, 초기값은 첫 렌더링 때 한번 사용된다.
  • state는 문자열, 숫자, boolean, 배열, null, 객체 등 여러가지 다양한 값을 넣을 수 있다.
  • 컴포넌트 내에서 여러 개 사용 가능하며, 각각의 상태는 독립적으로 관리된다.
import React, { useState } from 'react';

function Counter() {
  // useState 훅을 사용하여 count라는 상태와 그 상태를 업데이트할 수 있는 함수 setCount를 생성합니다.
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      {/* 버튼을 클릭할 때마다 setCount 함수를 사용하여 count 상태를 업데이트합니다. */}
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

export default Counter;

useEffect

컴포넌트가 렌더링될 때 특정한 동작을 수행하도록 하는 훅

  • useEffect(function, deps) 형태로 사용된다.
  • fuction에는 실행시킬 함수를 넣고, deps에는 의존성 배열을 담는다.
  • 의존성 배열에 어떤 것이 담겨있느냐에 따라 부수적인 효과 함수가 실행된다.

- 의존성 배열 없이 useEffect를 실행시키게 되면 페이지가 렌더링 될 때마다 데이터를 불러온다.

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

function ComponentWithoutDependencyArray() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);

    return () => clearInterval(interval);
  });

  return <div>Seconds: {seconds}</div>;
}

export default ComponentWithoutDependencyArray;

- 의존성 배열에 빈배열을 담을 경우에는 첫 렌더링 시에만 함수를 실행한다.

import React, { useEffect } from 'react';

function ComponentWithEmptyDependencyArray() {
  useEffect(() => {
    console.log('Effect runs only once because the dependency array is empty.');
  }, []);

  return <div>This is a component with an empty dependency array.</div>;
}

export default ComponentWithEmptyDependencyArray;

- 의존성 배열에 state값이나 props로 상속받은 데이터값 등을 담아주게 되면 해당값이 변할 때마다 함수를 실행한다.

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

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

  useEffect(() => {
    console.log('Effect runs whenever count changes:', count);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
    </div>
  );
}

export default ComponentWithDependencyArray;
  • 사이트 이펙트를 수행하거나 컴포넌트의 라이프사이클에 따른 작업을 수행하는 데 사용된다.

useRef

특정 DOM에 접근해 DOM 조작을 가능하게 하는 훅

React에서 DOM 요소나 다른 값을 참조할 때 사용되는 훅

DOM에 직접적으로 접근하거나 이전 값에 접근할 수 있음

  • DOM 요소에 접근하기
import React, { useRef, useEffect } from 'react';

function InputFocus() {
  const inputRef = useRef(null);

  useEffect(() => {
    // 컴포넌트가 마운트되면 input 요소에 포커스를 줍니다.
    inputRef.current.focus();
  }, []);

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus Input</button>
    </div>
  );
}

export default InputFocus;

useRef를 사용해 input 요소에 대한 참조를 생성한다.
useEffect를 사용해 컴포넌트가 마운트될 때 input 요소에 자동으로 포커스를 준다.
또한 버튼을 클릭해 input 요소에 다시 포커스를 줄 수 있다.

  • 이전 값 유지하기
import React, { useState, useRef } from 'react';

function PreviousValue() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();

  // 컴포넌트가 렌더링될 때마다 현재 count 값을 prevCountRef에 저장합니다.
  useEffect(() => {
    prevCountRef.current = count;
  });

  const prevCount = prevCountRef.current;

  return (
    <div>
      <p>Current count: {count}</p>
      <p>Previous count: {prevCount !== undefined ? prevCount : 'N/A'}</p>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
    </div>
  );
}

export default PreviousValue;

useRef를 사용해 이전 값에 대한 참조를 생성한다.
useEffect를 사용해 컴포넌트가 렌더링될 때마다 현재 count값을 prevCountRef에 저장하고, 그 값을 이용해 이전 값에 접근한다.

useCallback

메모이제이션된 콜백함수를 생성하는 데 사용되는 훅

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

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

  // 콜백 함수를 생성합니다. count가 변경될 때만 함수가 재생성됩니다.
  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <h1>Parent Component</h1>
      <p>Count: {count}</p>
      {/* ChildComponent에 콜백 함수를 props로 전달합니다. */}
      <ChildComponent onClick={handleClick} />
    </div>
  );
}

function ChildComponent({ onClick }) {
  return (
    <div>
      <h2>Child Component</h2>
      {/* 받은 콜백 함수를 이용하여 버튼을 렌더링합니다. */}
      <button onClick={onClick}>Increment Count</button>
    </div>
  );
}

export default ParentComponent;
  • useCallback을 사용하면 성능 향상을 이룰 수 있다.
  • 특히, 자식 컴포넌트에 콜백 함수를 props로 전달할 때 유용하다.

useMemo

계산 비용이 많이 드는 함수의 반환 값을 기억(memory)하여, 동일한 계산을 반복하지 않고 이전에 계산된 값을 재사용할 때 사용된다.

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

function FibonacciCalculator({ n }) {
  // useMemo를 사용하여 fibonacci 함수의 반환 값을 기억합니다.
  const fibNumber = useMemo(() => {
    function fibonacci(num) {
      if (num <= 1) return num;
      return fibonacci(num - 1) + fibonacci(num - 2);
    }
    return fibonacci(n);
  }, [n]);

  return (
    <div>
      <p>
        Fibonacci number at position {n} is {fibNumber}
      </p>
    </div>
  );
}

function App() {
  const [number, setNumber] = useState(1);

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(parseInt(e.target.value))}
      />
      <FibonacciCalculator n={number} />
    </div>
  );
}

export default App;
  • 렌더링 성능을 최적화하는 데 사용한다.

React Hooks의 장점

- 코드 재사용과 가독성 향상

상태 로직을 여러 컴포넌트에서 추상화할 수 있다.
코드 중복을 줄이고 컴포넌트 간의 로직을 재사용할 수 있다.
또한 함수형 컴포넌트는 일반적으로 클래스 컴포넌트보다 간결하며 가독성이 높아진다.

- 클래스 컴포넌트의 단점 극복

클래스 컴포넌트는 복잡한 상태 로직을 가질 경우 코드가 복잡해지고 이해하기 어려울 수 있다.
=> Hooks를 사용하면 함수형 컴포넌트에서도 클래스 컴포넌트의 기능을 사용할 수 있으므로, 클래스 컴포넌트의 단점을 극복할 수 있다.

- 테스트 용이성

컴포넌트 로직을 더 작은 함수 단위로 분리할 수 있다.
=> 테스트하기 쉽고 테스트 커버리지를 높일 수 있다.

- 함수형 프로그래밍 모델 강화

함수형 프로그래밍 모델을 강화하고, 순수 함수를 사용해 상태를 변경할 수 있도록 한다.
=> 더 예측 가능하고 안정적인 코드를 작성할 수 있게 해준다.

- React 최적화

Hooks를 사용하면 React는 함수형 컴포넌트와 관련된 최적화를 수행할 수 있다.
=> 이는 성능을 향상시키고 메모리 누수와 같은 문제를 예방할 수 있게 도와준다.

- 비즈니스 로직 분리

컴포넌트의 상태 관리와 렌더링 로직을 분리할 수 있다.
=> 코드의 유지 보수성을 높이고 개발자가 컴포넌트의 동작을 더 쉽게 이해할 수 있도록 도와준다.

함수형 컴포넌트에서 클래스형 컴포넌트의 라이프 사이클 메소드를 비슷하게 사용하는 방법

함수형 컴포넌트에서 클래스형 컴포넌트의 라이프사이클 메서드와 유사한 기능을 구현하기 위해 useEffect 훅을 사용할 수 있다.

1. componentDidMount

컴포넌트가 처음으로 렌더링될 때 실행된다.

useEffect(() => {
  // componentDidMount에 해당하는 작업 수행
}, []);

2. componentDidUpdate

컴포넌트가 업데이트될 때마다 실행된다.

useEffect(() => {
  // componentDidUpdate에 해당하는 작업 수행
}, [dependency]);

3. componentWillUnmount

컴포넌트가 언마운트되기 전에 실행된다.

useEffect(() => {
  return () => {
    // componentWillUnmount에 해당하는 작업 수행
  };
}, []);
profile
개발과 지식의 성장을 즐기는 개발자

0개의 댓글