Prop Drilling은 부모 컴포넌트에서 필요한 데이터나 함수를 자식 컴포넌트에 전달하기 위해 여러 단계의 props를 통해 데이터를 전달하는 과정입니다. 예를 들어, 최상위 컴포넌트에서 깊숙한 자손 컴포넌트에 데이터를 전달해야 할 때, 그 사이의 모든 중간 컴포넌트가 이 데이터를 받아 전달해야 합니다.
// App -> ComponentA -> ComponentB -> ComponentC
function ComponentA({ data }) {
return <ComponentB data={data} />;
}
function ComponentB({ data }) {
return <ComponentC data={data} />;
}
function ComponentC({ data }) {
return <div>{data}</div>;
}
위 코드처럼 data를 가장 깊은 자손 컴포넌트인 ComponentC로 전달하려면 중간의 ComponentA와 ComponentB에서도 data를 받아 전달해주어야 합니다. Prop Drilling이 발생하면 컴포넌트가 많아질수록 코드가 비효율적이 되고, 유지보수가 어려워집니다.
1) Context API 사용
import React, { createContext, useContext } from 'react';
const DataContext = createContext();
function App() {
const data = "Hello from Context!";
return (
<DataContext.Provider value={data}>
<ComponentA />
</DataContext.Provider>
);
}
function ComponentC() {
const data = useContext(DataContext);
return <div>{data}</div>;
}
2) 상태 관리 라이브러리 사용 (Redux, Recoil, Zustand 등)
3) 리액트 쿼리 (React Query) 사용
React Query는 서버 데이터를 클라이언트에서 손쉽게 캐시하고 상태를 공유할 수 있게 하므로, 자식 컴포넌트로 데이터를 직접 전달하지 않아도 됩니다.
import { useQuery } from 'react-query';
function ComponentA() {
const { data, isLoading, error } = useQuery('fetchData', fetchDataFromAPI);
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return <ComponentB data={data} />;
}
4) 컴포넌트 구조 개선
function useUserData(userId) {
const [userData, setUserData] = useState(null);
useEffect(() => {
fetchUserData(userId).then(setUserData);
}, [userId]);
return userData;
}