Frontend/react

React Hooks

dddzr 2024. 2. 24. 20:52

React Hooks

Hooks 는 리액트 v16.8 에 새로 도입된 기능으로서, 기존의 함수형 컴포넌트에서 할 수 없었던 다양한 작업을 할 수 있게 해줍니다.

함수형 컴포넌트에서 상태(state)와 생명주기(lifecycle) 메서드를 사용할 수 있도록 하는 기능입니다.

코드를 더 간결하고 가독성 있게 작성할 수 있습니다.

 

*함수형 컴포넌트, 클래스형 컴포넌트

https://sumni.tistory.com/69

 

react Component

React Component 비교 Class Component 많은 기능제공, 대신 코드길고복잡, 성능느림 - provide more features - longer code - more complex code - slower performance Functional Component 적은 기능제공, 코드 간단, 성능빠름 - provi

sumni.tistory.com

 

종류

useState

  • 상태를 추가하고 관리하는 Hook.
  • useState를 사용하여 상태를 선언하면 React는 해당 상태를 관리하고 상태가 변경될 때마다 컴포넌트를 자동으로 리렌더링합니다.
import React, { useState } from 'react';

function Counter() {
  // count 상태와 count를 업데이트하는 setCount 함수를 선언합니다.
  // 0을 초기값으로 설정
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      {/* 버튼 클릭 시 count를 1씩 증가시키는 함수를 호출합니다. */}
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default Counter;

 

useEffect

  • React 컴포넌트의 생명주기 메서드를 함수형 컴포넌트에서 사용할 수 있도록 해주는 Hook.
  • 컴포넌트가 렌더링/마운트/업데이트/언마운트될 때 등의 시점에서 특정 작업을 수행.
  • useEffect 함수는 두 개의 인자를 받습니다. 첫 번째 인자는 특정 작업을 수행하는 함수이고, 두 번째 인자는 의존성 배열(dependency array)입니다. 의존성 배열에 포함된 값들이 변경될 때마다 첫 번째 인자 함수가 실행됩니다.
  • useEffect를 사용하여 비동기 작업을 수행하거나, 외부 데이터를 불러오는 등의 작업을 수행할 수 있습니다.
import React, { useState, useEffect } from 'react';

function Timer() {
  // time 상태와 time을 업데이트하는 setTime 함수를 선언합니다.
  const [time, setTime] = useState(0);

  // 컴포넌트가 렌더링될 때마다 time을 1초마다 업데이트합니다.
  useEffect(() => {
    const timerId = setInterval(() => {
      setTime(prevTime => prevTime + 1);
    }, 1000);

    // 컴포넌트가 언마운트될 때 타이머를 정리합니다.
    return () => clearInterval(timerId);
  }, []);

  return (
    <div>
      <p>Time: {time} seconds</p>
    </div>
  );
}

export default Timer;

 

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

function Timer() {
  // time 상태와 time을 업데이트하는 setTime 함수를 선언합니다.
  const [time, setTime] = useState(0);
  const [isRunning, setIsRunning] = useState(true);

  // 컴포넌트가 렌더링될 때마다 time을 1초마다 업데이트합니다.
  useEffect(() => {
    // 타이머가 실행되는 조건을 추가합니다.
    if (isRunning) {
      const timerId = setInterval(() => {
        setTime(prevTime => prevTime + 1);
      }, 1000);

      // 컴포넌트가 언마운트될 때 타이머를 정리합니다.
      return () => clearInterval(timerId);
    }
  }, [isRunning]); // isRunning 값이 변경될 때만 useEffect가 실행됩니다.

  const handleToggle = () => {
    setIsRunning(prevIsRunning => !prevIsRunning);
  };

  return (
    <div>
      <p>Time: {time} seconds</p>
      <button onClick={handleToggle}>{isRunning ? 'Pause' : 'Resume'}</button>
    </div>
  );
}

export default Timer;

 

useContext

부모 컴포넌트에서 전역적으로 상태를 공유할 수 있도록 해주는 훅입니다.

import React, { useContext } from 'react';

// Context 생성
const ThemeContext = React.createContext('light');

// 컴포넌트 정의
function ThemeButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme }}>Themed Button</button>;
}

// 사용 예시
function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemeButton />
    </ThemeContext.Provider>
  );
}

 

useReducer

복잡한 상태 관리를 위해 사용되는 훅으로, useState와 비슷하지만 보다 복잡한 로직을 다룰 수 있습니다.

import React, { useReducer } from 'react';

// 리듀서 함수
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

// 컴포넌트 정의
function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

 

useCallback

메모이제이션된 콜백 함수를 생성하는 훅으로, 불필요한 렌더링을 방지할 수 있습니다.

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

function Counter() {
  const [count, setCount] = useState(0);
  
  const increment = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []);

  return (
    <div>
      Count: {count}
      <button onClick={increment}>Increment</button>
    </div>
  );
}

 

Custom Hook

React에서 자주 사용되는 로직을 재사용 가능한 함수로 추상화하여 컴포넌트 간에 공유할 수 있도록 하는 방법입니다.

1. 훅을 만들 함수 정의

커스텀 훅은 필요한 로직을 포함하는 함수로, 함수명이 use로 시작해야 합니다.

예시) URL에서 데이터를 가져오는 로직

import { useState, useEffect } from 'react';

// API를 호출하여 데이터를 가져오는 커스텀 훅
const useFetchData = (url) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (error) {
        setError(error);
        setLoading(false);
      }
    };

    fetchData();

    // 컴포넌트가 언마운트될 때 정리
    return () => {
      // 실행 취소 및 정리 작업
    };
  }, [url]);

  return { data, loading, error };
};

export default useFetchData;

 

2. 훅을 사용할 컴포넌트에 적용

예시) useFetchData 커스텀 훅을 사용하여 데이터를 가져와서 로딩 상태에 따라 다른 컴포넌트를 렌더링하고 있습니다. 

import React from 'react';
import useFetchData from './useFetchData';

function MyComponent() {
  const { data, loading, error } = useFetchData('https://api.example.com/data');

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      {data && (
        <ul>
          {data.map(item => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default MyComponent;

 

'Frontend > react' 카테고리의 다른 글

socket.io (react)  (0) 2024.02.24
Redux 설치 및 사용법  (0) 2023.09.27
combineReducers  (0) 2023.09.27
react-router-dom 버전6 변경 사항  (0) 2023.09.25
React Router Dom 설정(버전 5.x, 6링크)  (0) 2023.09.25