useState, useEffect 외에도, 특정 상황에서 유용하게 사용되는 여러 내장 Hook들이 있습니다.useRefuseRef는 두 가지 주요 목적을 위해 사용되는 Hook입니다.ref 속성을 통해 특정 JSX 엘리먼트를 직접 참조할 수 있습니다. 이를 통해 해당 DOM 노드의 값을 읽거나, 포커스를 맞추는 등의 작업을 할 수 있습니다. (e.g., 비제어 컴포넌트의 값 읽기)useState와 달리, useRef로 관리되는 .current 프로퍼티의 값은 변경되어도 컴포넌트가 다시 렌더링되지 않습니다. 컴포넌트의 전체 생명주기 동안 값을 유지해야 할 때(e.g., 타이머 ID 저장) 유용합니다.useReduceruseState의 대안으로, 복잡한 상태 로직을 관리할 때 유용합니다.const [state, dispatch] = useReducer(reducer, initialState);state: 현재 상태.dispatch: 상태 변경을 유발하는 "액션(Action)"을 발생시키는 함수.reducer: (state, action)을 인자로 받아, 새로운 상태를 반환하는 순수 함수.reducer)이 컴포넌트 외부로 분리되어, 상태 관리가 더 체계적이고 예측 가능해집니다.useContextuseContext: Context API와 함께 사용하여, Props 전달 없이도 컴포넌트 트리 전반에 걸쳐 데이터를 전역적으로 공유할 수 있게 해줍니다. (자세한 내용은 전역 상태 관리에서)createBrowserRouter & <RouterProvider>:
createBrowserRouter를 사용하여 라우트 설정을 객체 형태로 정의하고, <RouterProvider>를 통해 앱에 라우터를 제공합니다.<Link>:
to)로 URL만 변경하여 클라이언트 사이드에서 페이지를 전환합니다. (<a> 태그 대신 사용)<Outlet />:
useParams:
/products/:productId) 값을 객체로 가져오는 Hook입니다.useNavigate:
createContext로 Context를 생성하고, Provider로 데이터를 제공하며, useContext로 데이터를 소비합니다.value가 변경되면, 해당 Context를 구독하는 모든 컴포넌트가 리렌더링되어, 복잡한 앱에서는 성능 문제가 발생할 수 있습니다.Context API의 단점을 보완하고, 더 강력하고 체계적인 상태 관리를 위해 외부 라이브러리를 사용합니다.
Zustand:
Context의 복잡성과 보일러플레이트를 줄여주는, 매우 간결하고 직관적인 전역 상태 관리 라이브러리.<Provider>로 감쌀 필요가 없어 설정이 매우 간단합니다.create 함수 하나로 상태(state)와 상태 변경 함수(action)를 포함하는 스토어(Store)를 생성할 수 있습니다.// store/counterStore.js
import { create } from 'zustand';
const useCounterStore = create((set) => ({
count: 0,
increase: () => set((state) => ({ count: state.count + 1 })),
}));
// components/Counter.js
function Counter() {
const { count, increase } = useCounterStore();
return <button onClick={increase}>{count}</button>;
}
useRef는 DOM에 직접 접근하거나 리렌더링 없는 값 저장을 위해, useReducer는 복잡한 상태 로직을 체계적으로 관리하기 위해 사용됩니다.<Link>로 페이지를 전환하고 <Outlet />으로 중첩 레이아웃을 구성합니다.