728x90

React에서 useImperativeHandle()은 부모 컴포넌트가 자식 컴포넌트의 메서드나 프로퍼티를 직접적으로 접근할 수 있게 해줍니다. 이를 통해 자식 컴포넌트의 특정 기능에 대한 제어를 부모 컴포넌트에서 수행할 수 있습니다.

useImperativeHandle()은 useRef()와 함께 사용됩니다. useRef()를 사용하여 자식 컴포넌트의 인스턴스를 생성하고, useImperativeHandle()을 사용하여 부모 컴포넌트가 접근 가능한 메서드나 프로퍼티를 반환합니다.

예를 들어, 다음과 같은 자식 컴포넌트가 있다고 가정해 봅시다.

import { forwardRef, useImperativeHandle, useState } from "react";

const ChildComponent = forwardRef((props, ref) => {
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount(count + 1);
  };

  useImperativeHandle(ref, () => ({
    increment: incrementCount,
    count
  }));

  return <div>{count}</div>;
});

export default ChildComponent;

useImperativeHandle()은 ref와 함께 사용되며, ref는 자식 컴포넌트의 인스턴스를 가리킵니다. useImperativeHandle()의 첫 번째 매개변수로는 ref가 전달되며, 두 번째 매개변수로는 부모 컴포넌트에서 접근 가능한 메서드나 프로퍼티를 반환하는 함수가 전달됩니다.

위의 코드에서는 incrementCount() 메서드와 count 프로퍼티를 반환하고 있습니다. 부모 컴포넌트에서는 ref.current.increment()를 호출하여 자식 컴포넌트의 incrementCount() 메서드를 실행할 수 있습니다. 또한, ref.current.count를 통해 자식 컴포넌트의 count 프로퍼티 값을 가져올 수도 있습니다.

부모 컴포넌트에서는 다음과 같이 자식 컴포넌트의 메서드를 호출할 수 있습니다.

import { useRef } from "react";
import ChildComponent from "./ChildComponent";

function ParentComponent() {
  const childRef = useRef(null);

  const handleClick = () => {
    childRef.current.increment();
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleClick}>Increment Child Count</button>
    </div>
  );
}

export default ParentComponent;

위의 코드에서는 ChildComponent를 부모 컴포넌트에서 사용하고 있으며, useRef()를 사용하여 childRef를 생성합니다. 이후, childRef.current.increment()을 호출하여 자식 컴포넌트의 incrementCount() 메서드를 실행하게 됩니다. 이를 통해 자식 컴포넌트의 count 값을 증가시킬 수 있습니다.

useImperativeHandle()은 부모 컴포넌트에서 자식 컴포넌트를 제어해야 하는 경우에 유용합니다. 하지만 이를 남용하면 컴포넌트 간의 결합도가 높아질 수 있으므로 주의해야 합니다.

React 18에서는 useImperativeHandle()에 대한 문법적 변경이 없습니다. 다만, React 18에서는 Concurrent Mode가 기본적으로 활성화되며, 이를 활용하여 컴포넌트의 성능을 개선할 수 있습니다. Concurrent Mode를 활성화하면 useImperativeHandle()을 사용할 때, 부모 컴포넌트가 자식 컴포넌트의 메서드를 호출할 때 발생할 수 있는 성능 문제를 해결할 수 있습니다.

아래는 React 18에서 Concurrent Mode를 사용하는 예시입니다.

import { forwardRef, useImperativeHandle, useState } from "react";

const ChildComponent = forwardRef((props, ref) => {
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount(count + 1);
  };

  useImperativeHandle(ref, () => ({
    increment: incrementCount,
    count
  }));

  return <div>{count}</div>;
});

export default ChildComponent;
import { useRef } from "react";
import ChildComponent from "./ChildComponent";

function ParentComponent() {
  const childRef = useRef(null);

  const handleClick = () => {
    setTimeout(() => {
      childRef.current.increment();
    }, 0);
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleClick}>Increment Child Count</button>
    </div>
  );
}

export default ParentComponent;

위의 코드에서는 handleClick() 함수에서 setTimeout()을 사용하여 childRef.current.increment()을 비동기적으로 호출하고 있습니다. 이를 통해 Concurrent Mode를 활용하여 성능을 개선할 수 있습니다.


내저장소 바로가기 luxury515

'Front-end > React.js' 카테고리의 다른 글

React Hook : useDebugValue()  (0) 2023.04.15
React Hook : useLayoutEffect()  (0) 2023.04.15
React Hook : useRef()  (0) 2023.04.15
React Hook : useMemo()  (0) 2023.04.15
React Hook : useCallback()  (0) 2023.04.15
728x90

useRef()는 React 함수형 컴포넌트에서 DOM 요소에 접근하거나, 다른 목적으로 컴포넌트 내에서 변수를 유지하는 데 사용되는 Hook입니다.

React 18에서는 useRef()를 사용하여 컴포넌트 내부에서 mutable한 값, 즉 변경 가능한 값을 관리할 수 있습니다. 이전에는 클래스 컴포넌트에서 this.statethis.instanceVariable과 같은 mutable한 값들을 관리했지만, 이제 함수형 컴포넌트에서도 useRef()를 사용하여 이를 처리할 수 있습니다.

useRef()는 함수형 컴포넌트에서 클래스 컴포넌트의 인스턴스 변수와 유사한 역할을 합니다. 그러나 인스턴스 변수와 달리 useRef()를 사용하여 관리하는 변수의 변경은 컴포넌트 렌더링을 다시 하지 않습니다.

useRef()는 보통 DOM 요소에 접근하기 위해 사용됩니다. 예를 들어, 다음과 같이 useRef()를 사용하여 <input> 요소에 접근할 수 있습니다.

import { useRef } from 'react';

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

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleClick}>Focus the input</button>
    </div>
  );
}

이 코드에서는 inputRef라는 변수를 선언하고, 이를 <input> 요소의 ref prop에 할당합니다. useRef()의 초기값은 null로 설정됩니다. 그 다음으로, handleClick() 함수에서는 inputRef.current를 사용하여 <input> 요소에 접근하고, focus() 메서드를 호출하여 해당 요소에 포커스를 설정합니다.

또한 useRef()를 사용하여 컴포넌트 내에서 변수를 유지할 수도 있습니다. 이를 통해 컴포넌트 렌더링 간에 상태를 유지하거나, 이전 값과 현재 값을 비교하고, 다른 목적으로 사용할 수 있습니다. 예를 들어, 다음과 같이 useRef()를 사용하여 컴포넌트의 이전 상태를 저장할 수 있습니다.

import { useRef, useEffect } from 'react';

function MyComponent({ value }) {
  const prevValueRef = useRef(null);

  useEffect(() => {
    prevValueRef.current = value;
  }, [value]);

  const prevValue = prevValueRef.current;

  return (
    <div>
      <p>Current value: {value}</p>
      <p>Previous value: {prevValue}</p>
    </div>
  );
}

죄송합니다. 앞 부분을 놓쳐서 다시 적겠습니다.

useRef()를 사용하여 prevValueRef 변수를 만들고, 이 변수를 사용하여 value의 변경을 감시합니다. useEffect()value가 변경될 때마다 호출됩니다. useEffect()의 콜백 함수에서는 prevValueRef.current를 사용하여 이전 값을 value로 업데이트합니다. 마지막으로, prevValue 변수를 사용하여 이전 값을 렌더링합니다.

useRef()를 사용하여 컴포넌트에서 변수를 관리하는 방법은 무궁무진합니다. 예를 들어, useRef()를 사용하여 컴포넌트 내부의 특정 값을 추적하거나, 다른 컴포넌트나 모듈에서 공유할 수 있는 값을 저장하는 등 다양한 방법으로 활용할 수 있습니다.

사용시 주의점

하지만 주의해야 할 점도 있습니다. useRef()를 사용하여 상태를 관리하면, 해당 상태가 변경되었을 때 컴포넌트의 렌더링이 다시 발생하지 않습니다. 이는 렌더링 간에 변수 값이 변경되어도, 화면에 반영되지 않을 수 있다는 것을 의미합니다. 때문에, 변경되는 값을 렌더링에 반영하고 싶다면, 상태(State)나 prop을 사용하는 것이 좋습니다.

이상으로 useRef()에 대한 설명을 마칩니다. useRef()는 React Hooks 중 하나로, 함수형 컴포넌트에서 DOM 요소에 접근하거나, 다른 목적으로 컴포넌트 내에서 변수를 유지하는 데 사용됩니다. useRef()를 사용하여 컴포넌트 내부에서 mutable한 값을 관리할 수 있으며, 컴포넌트 렌더링 간에 상태를 유지할 수도 있습니다. 단, 이전 값과 현재 값을 비교하거나, 다른 목적으로 사용할 수 있습니다.


내저장소 바로가기 luxury515

'Front-end > React.js' 카테고리의 다른 글

React Hook : useLayoutEffect()  (0) 2023.04.15
React Hook : useImperativeHandle()  (0) 2023.04.15
React Hook : useMemo()  (0) 2023.04.15
React Hook : useCallback()  (0) 2023.04.15
React Hook : useReducer()  (0) 2023.04.15
728x90

React에서 useMemo()는 컴포넌트에서 렌더링할 때 특정 값을 "메모이제이션"하여, 렌더링 성능을 최적화하는 방법 중 하나입니다.

일반적으로, 컴포넌트 내부에서 매번 호출되는 계산량이 큰 함수나 복잡한 연산을 수행하는 함수가 있다면, 매번 렌더링할 때마다 함수가 다시 실행되어 성능에 영향을 줄 수 있습니다.

이때 useMemo()를 사용하면, 함수의 반환값을 메모이제이션하여, 이전에 계산한 결과가 다시 필요할 때는 함수를 재실행하지 않고 이전에 저장된 결과값을 사용할 수 있습니다. 이는 성능 최적화에 도움을 주며, 불필요한 계산을 줄일 수 있습니다.

useMemo()는 다음과 같은 문법으로 사용할 수 있습니다.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useMemo()는 두 개의 인자를 받습니다. 첫 번째 인자는 메모이제이션할 함수를 입력하고, 두 번째 인자는 의존성 배열(Dependencies array)을 입력합니다.

의존성 배열은 메모이제이션된 값이 사용되는 값들을 배열 형태로 입력합니다. 이 배열에 있는 값들 중 하나라도 변경되면, 메모이제이션된 값이 다시 계산됩니다. 만약 의존성 배열이 빈 배열([])로 입력되면, 메모이제이션된 값은 컴포넌트가 마운트될 때만 계산됩니다.

다음은 예제 코드입니다. getExpensiveNumber() 함수는 매우 무거운 계산을 수행하는 함수이므로, useMemo()를 사용하여 이전에 계산한 결과를 메모이제이션합니다.

import { useMemo, useState } from 'react';

function getExpensiveNumber(num) {
  // 무거운 계산을 수행하는 함수
  let result = 0;
  for (let i = 0; i < num * 10000000; i++) {
    result += Math.random();
  }
  return result;
}

function MyComponent({ a, b }) {
  const [count, setCount] = useState(0);

  const memoizedValue = useMemo(() => {
    return getExpensiveNumber(count);
  }, [count]);

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

위 예제에서 getExpensiveNumber()함수는 useMemo()를 사용하여 메모이제이션됩니다. 이 함수count값이 변경될 때마다 호출되며, 이전에 계산된 결과가 존재한다면, 메모이제이션된 값을 반환합니다. 만약 이전에 계산된 결과가 없다면, 새로운 값을 계산합니다. 이를 통해, getExpensiveNumber() 함수의 불필요한 계산을 줄여 성능을 최적화할 수 있습니다.

성능향상해주는 보약? 이라고니 많이 먹으면? 여기저기 모든 함수에 hook으로 도배할까?

useMemo()는 성능 최적화를 위해 많이 사용되는 React Hook 중 하나입니다. 하지만, 모든 경우에 사용하기에는 적합하지 않을 수 있습니다. 예를 들어, 메모이제이션된 값이 자주 변경된다면, useMemo()를 사용해도 성능 최적화 효과가 미미할 수 있습니다.

따라서 useMemo()는 주로 렌더링 성능이 중요한 경우에 사용되며, 컴포넌트 내부에서 매번 호출되는 계산량이 큰 함수나 복잡한 연산을 수행하는 함수를 최적화할 때 효과적입니다.

주의사항

또한, useMemo()를 사용할 때는 의존성 배열을 잘 파악하여 사용해야 합니다. 의존성 배열에 필요하지 않은 값이 들어가면, 메모이제이션된 값이 불필요하게 재계산될 수 있습니다. 반면, 의존성 배열에 필요한 값이 빠져있으면, 메모이제이션된 값이 적절하지 않은 값으로 유지될 수 있습니다.

React 18에서는 useMemo()가 변경되지 않았으며, 여전히 위에서 설명한 방식으로 사용됩니다. 하지만, React 18에서는 useMemo()와 같은 Hook들을 더욱 효율적으로 사용할 수 있는 방법들이 추가될 예정이라고 하며, 이를 통해 더욱 성능 최적화를 할 수 있을 것입니다.


내저장소 바로가기 luxury515

'Front-end > React.js' 카테고리의 다른 글

React Hook : useImperativeHandle()  (0) 2023.04.15
React Hook : useRef()  (0) 2023.04.15
React Hook : useCallback()  (0) 2023.04.15
React Hook : useReducer()  (0) 2023.04.15
React Hook : useContext()  (0) 2023.04.15
728x90

React에서 useCallback()은 컴포넌트에서 성능을 최적화하기 위해 사용되는 Hook 중 하나입니다. 이 Hook은 메모이제이션된 함수를 반환하며, 이 함수는 컴포넌트가 렌더링될 때마다 새로 생성되지 않고 이전에 생성된 함수를 재사용합니다. 이를 통해 불필요한 함수 생성 및 연산을 방지하여 성능을 향상시킵니다.

useCallback()은 다음과 같은 구문으로 사용할 수 있습니다.

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useCallback()은 두 개의 인자를 받습니다. 첫 번째 인자는 메모이제이션된 함수이며, 두 번째 인자는 의존성 배열(dependency array)입니다. 두 번째 인자를 전달하지 않으면 useCallback()은 컴포넌트가 처음 마운트될 때 메모이제이션된 함수를 생성합니다. 의존성 배열에는 메모이제이션된 함수가 의존하는 값들을 나열합니다. 만약 의존성 배열에 있는 값이 변경되면, useCallback()은 새로운 메모이제이션된 함수를 생성합니다. 이 때, 새로 생성된 함수는 이전에 생성된 함수와 다를 수 있습니다.

다음은 useCallback()을 사용하여 의존성 변경을 추적하는 예제입니다.

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

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  const handleChange = useCallback((event) => {
    setText(event.target.value);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <input type="text" value={text} onChange={handleChange} />
    </div>
  );
}

export default App;

위 예제에서 handleChange 함수는 input 요소의 값이 변경될 때마다 호출됩니다. handleChange 함수는 setText 함수에 의존합니다. 그러나 setText 함수는 의존성 배열에 포함되어 있지 않습니다. 이 경우, 의존성 배열이 빈 배열([])로 설정되었으므로, useCallback()이 처음에 생성된 함수를 메모이제이션합니다. 그리고 이 함수는 항상 이전에 생성된 함수와 동일합니다.

하지만, setText 함수가 변경될 때마다 새로운 함수를 생성하려면, 의존성 배열에 setText 함수를 추가해야 합니다. 의존성 배열을 [setText]로 설정하면, setText 함수가 변경될 때마다 새로운 함수가 생성됩니다.

이제 의존성 배열을 [setText]로 설정하여 예제를 다시 실행해보면, input 요소의 값이 변경될 때마다 새로운 함수가 생성되는 것을 확인할 수 있습니다. 이전에는 새로운 함수가 생성되지 않았기 때문에, 불필요한 함수 호출이 발생할 수 있었습니다. 하지만 이제 useCallback()을 사용하여, setText 함수가 변경될 때마다 새로운 함수를 생성하므로, 불필요한 함수 호출을 방지하여 성능을 향상시킬 수 있습니다.


내저장소 바로가기 luxury515

'Front-end > React.js' 카테고리의 다른 글

React Hook : useRef()  (0) 2023.04.15
React Hook : useMemo()  (0) 2023.04.15
React Hook : useReducer()  (0) 2023.04.15
React Hook : useContext()  (0) 2023.04.15
React Hook : **`useEffect`** __()__  (0) 2023.04.15

+ Recent posts