안녕하세요, UI 개발자 여러분! React Hooks의 흥미진진한 세계로 뛰어들 준비가 되셨나요? 한동안 React로 작업해 왔다면 클래스 구성 요소가 상태 및 부작용을 관리하는 데 사용되던 시절을 기억할 것입니다. 그러나 시대가 변했고 React Hooks는 구성 요소를 구축하는 방식에 혁명을 일으켰습니다.
이 친절한 가이드에서는 10가지 필수 React Hooks를 살펴보고, 프로젝트에서 이를 이해하고 구현하는 데 도움이 되는 예제 튜토리얼을 제공합니다. Hooks를 처음 접하는 분이든 더 깊은 지식을 찾고 있는 분이든 이 게시물을 통해 도움을 받으실 수 있습니다. 좋아하는 음료를 들고 편안하게 React Hooks 모험을 함께 시작해 보세요!
가장 일반적으로 사용되는 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 함수를 사용하여 이를 업데이트합니다.
다음은 구성 요소에서 부작용을 수행할 수 있게 해주는 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를 사용하여 창 크기 조정을 위한 이벤트 리스너를 추가합니다. 정리 기능은 구성 요소가 마운트 해제될 때 리스너를 제거합니다.
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의 현재 테마 값에 액세스합니다.
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를 사용하여 증가 및 감소 작업이 포함된 카운터를 관리합니다.
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 다시 렌더링을 방지합니다.
Similar to useCallback, useMemo is used for optimization, but it memoizes the result of a computation.
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.
The useRef Hook provides a way to create a mutable reference that persists across re-renders.
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.
useImperativeHandle customizes the instance value that is exposed to parent components when using ref.
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.
useLayoutEffect is similar to useEffect, but it fires synchronously after all DOM mutations.
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.
Last but not least, useDebugValue can be used to display a label for custom hooks in React DevTools.
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.
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:
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.
Don't be afraid to experiment and combine different Hooks to solve complex problems. The React community is constantly coming up with new patterns and custom Hooks, so keep learning and sharing your discoveries!
I hope this friendly guide has helped you get a better grasp on React Hooks. Happy coding, and may your components be forever functional and hook-tastic!
"Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class." - React Documentation
Now go forth and hook it up! ??
以上がフックの例と反応の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。