>  기사  >  웹 프론트엔드  >  예제를 사용한 React Hooks

예제를 사용한 React Hooks

Susan Sarandon
Susan Sarandon원래의
2024-10-14 16:35:03168검색

React Hooks with Example

소개: React Hooks의 힘 수용하기

안녕하세요, UI 개발자 여러분! React Hooks의 흥미진진한 세계로 뛰어들 준비가 되셨나요? 한동안 React로 작업해 왔다면 클래스 구성 요소가 상태 및 부작용을 관리하는 데 사용되던 시절을 기억할 것입니다. 그러나 시대가 변했고 React Hooks는 구성 요소를 구축하는 방식에 혁명을 일으켰습니다.

이 친절한 가이드에서는 10가지 필수 React Hooks를 살펴보고, 프로젝트에서 이를 이해하고 구현하는 데 도움이 되는 예제 튜토리얼을 제공합니다. Hooks를 처음 접하는 분이든 더 깊은 지식을 찾고 있는 분이든 이 게시물을 통해 도움을 받으실 수 있습니다. 좋아하는 음료를 들고 편안하게 React Hooks 모험을 함께 시작해 보세요!

1. useState: 손쉬운 상태 관리

가장 일반적으로 사용되는 Hook인 useState로 시작해 보겠습니다. 이 작은 보석을 사용하면 클래스 없이 기능적 구성 요소에 상태를 추가할 수 있습니다.

작동 원리

useState Hook은 현재 상태 값과 이를 업데이트하는 함수라는 두 가지 요소가 포함된 배열을 반환합니다. 다음은 간단한 예입니다.

import React, { useState } from 'react';

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

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

이 예에서는 버튼을 클릭할 때마다 증가하는 카운터를 생성합니다. useState 후크는 카운트를 0으로 초기화하고 setCount 함수를 사용하여 이를 업데이트합니다.

useState를 사용하는 경우

  • 기능 컴포넌트에서 로컬 상태를 관리해야 하는 경우
  • 숫자, 문자열, 부울과 같은 간단한 데이터 유형의 경우
  • 기본 상태 관리를 위해 클래스 구성 요소의 복잡성을 피하고 싶을 때

2. useEffect: 부작용 처리

다음은 구성 요소에서 부작용을 수행할 수 있게 해주는 Hook인 useEffect입니다. 그것은 마치 componentDidMount, componentDidUpdate, 그리고 componentWillUnmount가 모두 하나로 통합된 것과 같습니다!

작동 원리

useEffect는 두 가지 인수, 즉 렌더링 후 실행할 함수와 선택적 종속성 배열을 사용합니다. 예는 다음과 같습니다.

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

function WindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);

    // Cleanup function
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // Empty dependency array means this effect runs once on mount

  return <div>Window width: {width}px</div>;
}

이 예에서는 useEffect를 사용하여 창 크기 조정을 위한 이벤트 리스너를 추가합니다. 정리 기능은 구성 요소가 마운트 해제될 때 리스너를 제거합니다.

useEffect를 사용하는 경우

  • 데이터 가져오기용
  • 구독 또는 이벤트 리스너 설정
  • DOM 수동 변경
  • 렌더링에 직접적인 영향을 주지 않는 로깅이나 기타 부작용

3. useContext: 손쉽게 컨텍스트 소비하기

useContext 후크는 렌더링 소품이나 고차 구성요소 없이 기능 구성요소에서 컨텍스트를 소비하는 방법을 제공합니다.

작동 원리

먼저 React.createContext()를 사용하여 컨텍스트를 생성한 다음 useContext Hook을 사용하여 이를 사용합니다.

import React, { useContext } from 'react';

const ThemeContext = React.createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>I'm styled by theme context!</button>;
}

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemedButton />
    </ThemeContext.Provider>
  );
}

이 예에서 ThemedButton은 useContext 후크를 사용하여 ThemeContext의 현재 테마 값에 액세스합니다.

useContext를 사용하는 경우

  • React 구성 요소 트리에 대해 "전역"으로 간주할 수 있는 데이터를 공유해야 하는 경우
  • 프롭 드릴링(다양한 구성요소 레벨을 통해 프롭 전달)을 방지하려면
  • 테마 설정, 사용자 인증 또는 기타 애플리케이션 전체 데이터용

4. useReducer: 복잡한 상태 로직 관리

useState가 충분하지 않으면 useReducer가 도움을 줍니다. 더욱 복잡한 상태 로직을 관리하는 데 특히 유용합니다.

작동 원리

useReducer는 리듀서 함수와 초기 상태를 취하고 디스패치 메소드와 쌍을 이루는 현재 상태를 반환합니다.

import React, { useReducer } from 'react';

const initialState = {count: 0};

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, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

이 예에서는 useReducer를 사용하여 증가 및 감소 작업이 포함된 카운터를 관리합니다.

useReducer를 사용하는 경우

  • 여러 하위 값이 포함된 복잡한 상태 논리가 있는 경우
  • 다음 상태가 이전 상태에 따라 달라지는 경우
  • 심층 업데이트를 실행하는 구성 요소의 성능을 최적화하려는 경우

5. useCallback: 성능 최적화

useCallback Hook은 콜백 함수를 메모하여 구성 요소의 성능을 최적화하는 데 도움이 될 수 있습니다.

작동 방식

useCallback은 종속성 중 하나가 변경된 경우에만 변경되는 메모된 버전의 콜백을 반환합니다.

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

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

  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []);

  return (
    <div>
      <ChildComponent onIncrement={increment} />
      <p>Count: {count}</p>
    </div>
  );
}

function ChildComponent({ onIncrement }) {
  console.log('ChildComponent rendered');
  return <button onClick={onIncrement}>Increment</button>;
}

이 예에서는 useCallback을 사용하여 증분 함수를 메모하여 불필요한 ChildComponent 다시 렌더링을 방지합니다.

When to use useCallback

  • When passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders
  • In combination with useMemo for creating memoized callbacks

6. useMemo: Memoizing Expensive Computations

Similar to useCallback, useMemo is used for optimization, but it memoizes the result of a computation.

How it works

useMemo takes a function and an array of dependencies, and only recomputes the memoized value when one of the dependencies has changed:

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

function ExpensiveComponent({ list }) {
  const [filter, setFilter] = useState('');

  const filteredList = useMemo(() => {
    console.log('Filtering list...');
    return list.filter(item => item.toLowerCase().includes(filter.toLowerCase()));
  }, [list, filter]);

  return (
    <div>
      <input
        type="text"
        value={filter}
        onChange={e => setFilter(e.target.value)}
        placeholder="Filter list"
      />
      <ul>
        {filteredList.map(item => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

In this example, we're using useMemo to memoize the filtered list, preventing unnecessary recalculations on every render.

When to use useMemo

  • For expensive calculations that don't need to be re-run on every render
  • When you want to avoid re-rendering child components unnecessarily
  • For referential equality checks in other Hooks' dependency arrays

7. useRef: Accessing DOM Elements and Storing Mutable Values

The useRef Hook provides a way to create a mutable reference that persists across re-renders.

How it works

useRef returns a mutable ref object whose .current property is initialized to the passed argument:

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

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

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} />;
}

In this example, we're using useRef to get a reference to the input element and focus it when the component mounts.

When to use useRef

  • To access DOM elements directly
  • For storing mutable values that don't cause re-renders when updated
  • For keeping track of previous values in functional components

8. useImperativeHandle: Customizing Instance Value

useImperativeHandle customizes the instance value that is exposed to parent components when using ref.

How it works

useImperativeHandle should be used with forwardRef:

import React, { useRef, useImperativeHandle, forwardRef } from 'react';

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    getValue: () => {
      return inputRef.current.value;
    }
  }));

  return <input ref={inputRef} />;
});

function Parent() {
  const fancyInputRef = useRef();

  const handleClick = () => {
    fancyInputRef.current.focus();
    console.log(fancyInputRef.current.getValue());
  };

  return (
    <div>
      <FancyInput ref={fancyInputRef} />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
}

In this example, we're using useImperativeHandle to customize what instance value is exposed to the parent component.

When to use useImperativeHandle

  • When you want to customize the exposed instance value of a forwardRef component
  • To limit the exposed functionality of a child component to its parent

9. useLayoutEffect: Synchronous Effect Hook

useLayoutEffect is similar to useEffect, but it fires synchronously after all DOM mutations.

How it works

The signature is identical to useEffect, but it fires synchronously before the browser has a chance to paint:

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

function Tooltip() {
  const [tooltipHeight, setTooltipHeight] = useState(0);
  const tooltipRef = useRef();

  useLayoutEffect(() => {
    const height = tooltipRef.current.clientHeight;
    setTooltipHeight(height);
  }, []);

  return (
    <div>
      <div ref={tooltipRef}>Tooltip content</div>
      <p>The tooltip height is: {tooltipHeight}px</p>
    </div>
  );
}

In this example, we're using useLayoutEffect to measure the height of a DOM element synchronously before the browser paints.

When to use useLayoutEffect

  • When you need to make DOM measurements or mutations that should be applied synchronously before the browser paints
  • For animations that require measurements of DOM elements
  • When you want to avoid flickering caused by asynchronous updates

10. useDebugValue: Labeling Custom Hooks for DevTools

Last but not least, useDebugValue can be used to display a label for custom hooks in React DevTools.

How it works

useDebugValue accepts a value and an optional formatting function:

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

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  // ... Logic to determine if the friend is online ...

  useDebugValue(isOnline ? 'Online' : 'Offline');

  return isOnline;
}

function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

In this example, we're using useDebugValue to display the friend's online status in React DevTools.

When to use useDebugValue

  • In custom Hooks to provide more context about the Hook's state
  • For debugging complex custom Hooks
  • To improve the developer experience when working with custom Hooks

Conclusion: Mastering React Hooks

Wow, we've covered a lot of ground! From managing state with useState to optimizing performance with useMemo and useCallback, React Hooks offer a powerful and flexible way to build UI components. Let's recap the 10 Hooks we've explored:

  1. useState: For managing local state
  2. useEffect: For handling side effects
  3. useContext: For consuming context
  4. useReducer: For managing complex state logic
  5. useCallback: For optimizing performance of callbacks
  6. useMemo: For memoizing expensive computations
  7. useRef: For accessing DOM elements and storing mutable values
  8. useImperativeHandle: For customizing instance value
  9. useLayoutEffect: For synchronous effect execution
  10. useDebugValue: For labeling custom Hooks in DevTools

Remember, the key to mastering React Hooks is practice. Start by incorporating them into your projects one at a time. As you become more comfortable, you'll find that Hooks can significantly simplify your code and make your components more reusable and easier to understand.

복잡한 문제를 해결하기 위해 다양한 Hooks를 실험하고 결합하는 것을 두려워하지 마세요. React 커뮤니티는 지속적으로 새로운 패턴과 사용자 정의 Hook을 내놓고 있으므로 계속해서 배우고 발견한 내용을 공유하세요!

이 친절한 가이드가 React Hooks를 더 잘 이해하는 데 도움이 되었기를 바랍니다. 즐거운 코딩을 하시길 바랍니다. 구성 요소가 영원히 기능적이고 매력적이기를 바랍니다!

"후크는 React 16.8에 새로 추가된 기능입니다. 이를 통해 클래스를 작성하지 않고도 상태 및 기타 React 기능을 사용할 수 있습니다." - 반응 문서

이제 가서 연결해 보세요! ??

위 내용은 예제를 사용한 React Hooks의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.