React Hooks(2)

김진영·2024년 6월 20일
0

React

목록 보기
2/2

useState

useState는 함수형 컴포넌트에서 상태를 관리할 수 있게 해주고, 가장 기본적인 Hook입니다. 이를 사용하면 클래스 컴포넌트를 사용하지 않고도 상태를 가질 수 있습니다. useState는 초기 상태 값을 인자로 받아 상태 변수와 상태 변경 함수를 반환합니다.

import React, { useState } from 'react';

function Counter() {
  // count 상태 변수 선언, 초기 값은 0
  const [count, setCount] = useState(0);

  // 버튼 클릭 시 호출되는 함수
  const increment = () => {
    // count 상태를 현재 값 + 1로 업데이트
    setCount(count + 1);
  };

  return (
    <div>
      {/* 현재 카운트 값을 표시 */}
      <p>현재 카운트: {count}</p>
      {/* 버튼을 클릭하면 increment 함수 호출 */}
      <button onClick={increment}>카운트 증가</button>
    </div>
  );
}

export default Counter;

useEffect

useEffect는 React 함수형 컴포넌트에서 사이드 이펙트를 수행할 수 있게 해주는 Hook입니다. 이를 통해 컴포넌트가 마운트, 업데이트, 언마운트될 때 특정 작업을 수행할 수 있습니다. useEffect는 두 개의 인자를 받습니다. 첫 번째 인자는 실행할 함수, 두 번째 인자는 의존성 배열입니다.

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

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

function Example() {
  const [count, setCount] = useState(0); // count 상태 변수 선언, 초기 값은 0

  useEffect(() => {
    // 컴포넌트가 마운트될 때 실행
    console.log('컴포넌트가 마운트되었습니다.');

    // 컴포넌트가 언마운트될 때 실행되는 정리 함수
    return () => {
      console.log('컴포넌트가 언마운트되었습니다.');
    };
  }, []); // 빈 배열을 전달하여 컴포넌트가 마운트될 때 한 번만 실행

  const increment = () => {
    setCount(count + 1); // count 상태를 현재 값 + 1로 업데이트
  };

  return (
    <div>
      <p>현재 카운트: {count}</p> {/* 현재 카운트 값을 표시 */}
      <button onClick={increment}>카운트 증가</button> {/* 버튼을 클릭하면 increment 함수 호출 */}
    </div>
  );
}

export default Example;
  • useState(0): count 상태 변수 선언, 초기 값은 0.
  • useEffect(() => { ... }, []): 컴포넌트가 마운트될 때와 언마운트되기 전이나 업데이트되기 직전에 특정 작업을 수행.
    • 마운트될 때: '컴포넌트가 마운트되었습니다.'를 콘솔에 출력.
    • 언마운트되기 전이나 업데이트되기 직전에: '컴포넌트가 언마운트되거나 업데이트되기 직전에 실행됩니다.'를 콘솔에 출력.
  • increment 함수: 버튼 클릭 시 count 상태를 1씩 증가.
    useEffect는 기본적으로 렌더링된 직후에 실행되며, 두 번째 파라미터 배열에 의존성을 넣으면 해당 의존성 값이 변경될 때마다 실행됩니다. 정리(cleanup) 함수는 컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 실행됩니다.

useReducer

useReducer는 상태 관리 로직이 복잡해질 때 유용한 React Hook입니다. useState 대신에 사용할 수 있으며, Redux와 같은 상태 관리 라이브러리와 유사한 패턴을 제공합니다.useReducer는 세 가지 인자를 받습니다: 리듀서 함수, 초기 상태, (선택적) 초기화 함수입니다. 리듀서 함수는 현재 상태와 액션을 받아 새로운 상태를 반환합니다.

import React, { useReducer } from 'react';

// 리듀서 함수: 현재 상태와 액션을 받아 새로운 상태를 반환합니다.
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      // count 상태를 1 증가시킵니다.
      return { count: state.count + 1 };
    case 'decrement':
      // count 상태를 1 감소시킵니다.
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  // useReducer 사용: 리듀서 함수와 초기 상태를 전달하여 state와 dispatch를 반환합니다.
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      {/* 현재 카운트 값을 표시합니다. */}
      <p>현재 카운트: {state.count}</p>
      {/* 버튼을 클릭하면 'increment' 액션을 디스패치합니다. */}
      <button onClick={() => dispatch({ type: 'increment' })}>카운트 증가</button>
      {/* 버튼을 클릭하면 'decrement' 액션을 디스패치합니다. */}
      <button onClick={() => dispatch({ type: 'decrement' })}>카운트 감소</button>
    </div>
  );
}

export default Counter;

state

  • state는 현재 컴포넌트의 상태 값을 나타냅니다.
  • useReducer에 의해 관리되는 상태는 단일 객체로 표현될 수 있으며, 이 객체는 리듀서 함수에 의해 업데이트됩니다.
  • 예제에서 state{ count: 0 }와 같은 형태로 초기화됩니다.

dispatch

  • dispatch는 액션을 리듀서 함수로 보내는 함수입니다.
  • 액션은 상태를 변경하기 위한 정보를 포함한 객체입니다. 일반적으로 type 속성을 포함하며, 필요에 따라 추가 데이터를 포함할 수 있습니다.
  • dispatch를 호출하면, 리듀서 함수가 실행되어 현재 상태와 액션을 기반으로 새로운 상태를 반환합니다.

useReducer를 이용한 여러개의 Inpunt상태 관리

import React, { useReducer } from 'react';

// 리듀서 함수: 현재 상태와 액션을 받아 새로운 상태를 반환합니다.
function reducer(state, action) {
  switch (action.type) {
    case 'setInput':
      // 특정 필드의 값을 업데이트합니다.
      return { ...state, [action.name]: action.value };
    default:
      // 정의되지 않은 액션 타입에 대한 에러를 던집니다.
      console.error('처리되지 않은 액션 타입:', action.type);
      throw new Error('처리되지 않은 액션 타입: ' + action.type);
  }
}

function InputExample() {
  // useReducer 사용: 리듀서 함수와 초기 상태를 전달하여 state와 dispatch를 반환합니다.
  const [state, dispatch] = useReducer(reducer, { name: '', age: '', email: '' });

  // 인풋 필드 값이 변경될 때 호출되는 함수
  const handleChange = (e) => {
    dispatch({ type: 'setInput', name: e.target.name, value: e.target.value });
  };

  return (
    <div>
      {/* 이름 인풋 필드 */}
      <input 
        type="text" 
        name="name" 
        value={state.name} 
        onChange={handleChange} 
        placeholder="이름을 입력하세요" 
      />
      {/* 나이 인풋 필드 */}
      <input 
        type="text" 
        name="age" 
        value={state.age} 
        onChange={handleChange} 
        placeholder="나이를 입력하세요" 
      />
      {/* 이메일 인풋 필드 */}
      <input 
        type="email" 
        name="email" 
        value={state.email} 
        onChange={handleChange} 
        placeholder="이메일을 입력하세요" 
      />
      {/* 현재 인풋 필드의 값을 표시합니다. */}
      <p>현재 입력 값: 이름: {state.name}, 나이: {state.age}, 이메일: {state.email}</p>
    </div>
  );
}

export default InputExample;

useMemo

useMemo를 사용하면 함수 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있습니다. useMemo는 성능 최적화를 위해 값이 변경되지 않는 한 계산을 다시 하지 않도록 하는 React Hook입니다. 주로 계산 비용이 높은 작업이나 렌더링 중에 반복적으로 실행될 수 있는 작업을 최적화하는 데 사용됩니다.

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

const UseMemoSample = () => {
  // 두 개의 상태 변수 선언: numbers와 inputValue
  const [numbers, setNumbers] = useState([]);
  const [inputValue, setInputValue] = useState("");

  // numbers 배열이 변경될 때만 계산되는 평균값
  const average = useMemo(() => {
    console.log("평균값 계산 중...");
    if (numbers.length === 0) return 0;
    const sum = numbers.reduce((a, b) => a + b, 0);
    return sum / numbers.length;
  }, [numbers]);

  // inputValue가 변경될 때 호출되는 함수
  const handleInputChange = (e) => {
    setInputValue(e.target.value);
  };

  // 새로운 숫자를 추가하는 함수
  const addNumber = () => {
    const number = parseFloat(inputValue);
    setNumbers([...numbers, number]);
    setInputValue("");
  };

  return (
    <div>
      {/* 숫자를 추가하는 인풋 필드와 버튼 */}
      <input
        type="text"
        value={inputValue}
        onChange={handleInputChange}
        placeholder="숫자를 입력하세요"
      />
      <button onClick={addNumber}>숫자 추가</button>

      {/* 현재 numbers 배열의 값을 표시 */}
      <p>입력된 숫자: {numbers.join(", ")}</p>
      <p>평균값: {average}</p>
    </div>
  );
};

export default UseMemoSample;
  • useMemo는 두 번째 인자인 의존성 배열의 값이 변경될 때만 첫 번째 인자로 전달된 함수가 실행되어 값을 다시 계산합니다. 이를 통해 불필요한 계산을 방지하고 성능을 최적화할 수 있습니다.
  • 이 예제에서는 count가 변경될 때만 memoizedValue가 다시 계산되며, inputValuecount와 독립적으로 관리됩니다.

useCallback

useCallback은 함수형 컴포넌트에서 함수를 메모이제이션하는 데 사용됩니다. 특정 의존성 배열이 변경되지 않는 한 함수를 새로 생성하지 않고 이전에 생성된 함수를 재사용합니다. 이는 자식 컴포넌트에 콜백 함수를 props로 전달할 때 특히 유용하며, 불필요한 렌더링을 방지하여 성능을 최적화할 수 있습니다.다.

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

// List 컴포넌트: 리스트 아이템을 표시하며, 각 아이템을 클릭할 때 onItemClick 함수를 호출합니다.
const List = ({ items, onItemClick }) => {
  console.log('List 컴포넌트가 렌더링되었습니다.');
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index} onClick={() => onItemClick(item)}>
          {item}
        </li>
      ))}
    </ul>
  );
};

const UseCallbackSample = () => {
  // 두 개의 상태 변수 선언: count와 items
  const [count, setCount] = useState(0);
  const [items] = useState(['아이템1', '아이템2', '아이템3']);

  // onItemClick 함수는 count가 변경될 때만 새로 생성됩니다.
  const onItemClick = useCallback((item) => {
    console.log(`${item}이 클릭되었습니다.`);
  }, [count]);

  return (
    <div>
      <p>카운트: {count}</p>
      {/* 버튼을 클릭할 때 count 상태를 1 증가시킵니다. */}
      <button onClick={() => setCount(count + 1)}>카운트 증가</button>
      {/* List 컴포넌트에 items와 onItemClick을 props로 전달합니다. */}
      <List items={items} onItemClick={onItemClick} />
    </div>
  );
};

export default UseCallbackSample;

useRef

useRef는 함수형 컴포넌트에서 레퍼런스를 생성하는 데 사용됩니다. useRef로 생성된 객체는 컴포넌트의 생명주기 동안 유지되며, 값이 변경되어도 리렌더링을 일으키지 않습니다. 주로 DOM 요소에 접근하거나 이전 값을 저장하는 데 사용됩니다. 예를 들어, input 요소에 포커스를 설정하거나, 이전 값을 저장하여 비교하는 데 유용합니다.

import React, { useRef } from 'react';

const UseRefSample = () => {
  // inputRef는 input 요소를 참조합니다. 초기 값은 null입니다.
  const inputRef = useRef(null);

  // focusInput 함수는 버튼 클릭 시 input 요소에 포커스를 설정합니다.
  const focusInput = () => {
    // inputRef.current를 통해 input 요소에 접근하여 포커스를 설정합니다.
    inputRef.current.focus();
  };

  return (
    <div>
      {/* inputRef를 input 요소에 연결합니다. */}
      <input ref={inputRef} type="text" placeholder="여기에 입력하세요" />
      {/* 버튼을 클릭할 때 focusInput 함수를 호출합니다. */}
      <button onClick={focusInput}>포커스 설정</button>
    </div>
  );
};

export default UseRefSample;

이 예제는 useRef를 사용하여 input 요소에 접근하고 포커스를 설정하는 방법을 보여줍니다. useRef의 주요 장점은 컴포넌트의 생명주기 동안 레퍼런스를 유지하면서도 값이 변경되어도 리렌더링을 일으키지 않는다는 점입니다. 이는 DOM 요소에 직접 접근하거나 이전 값을 저장하여 비교할 때 매우 유용합니다.

Happy Coding!

0개의 댓글