
Props Drilling 문제 해결 방법 중 하나
컴포넌트 트리 전반에 걸쳐 데이터를 효율적으로 공유할 수 있게 해주는 기능이다.
Context를 사용하면, 데이터를 필요로 하는 컴포넌트가 트리 구조상 어디에 있든 상관없이 Provider로부터 직접 데이터에 접근할 수 있다.
createContext: 컨텍스트 객체 생성Context.Provider: 생성된 컨텍스트를 하위 컴포넌트들에게 제공(Provide), value prop을 통해 공유할 데이터를 전달useContext: Provider가 제공한 데이터에 접근(Consume)하는 훅import type { AccommodationType } from '@/types/accommodationType';
import { createContext } from 'react';
const AccommodationContext = createContext<AccommodationType | null>(null);
export const AccommodationProvider = AccommodationContext.Provider;
export default AccommodationContext;
createContext를 사용해 컨텍스트 객체를 생성한다.
import AccommodationContext from '@/features/search/contexts/AccommodationContext';
import { useContext } from 'react';
const useAccommodation = () => {
const context = useContext(AccommodationContext);
if (!context) {
throw new Error(
'useAccommodation은 AccommodationProvider 내에서만 사용 가능',
);
}
return context;
};
export default useAccommodation;
이때 커스텀 훅을 함께 만들어두면, 컨텍스트를 사용할 때마다 발생하는 특정 반복 작업을 줄이고 코드를 깔끔하게 유지할 수 있다.
여기서는 훅이 프로바이더 내부에서만 사용되도록 했다. (context === null인 경우)
const AccommodationList = ({
accommodations,
}: {
accommodations: AccommodationResponse;
}) => {
return (
<AccommodationListContainer>
{accommodations?.map((item: AccommodationType) => (
<AccommodationProvider key={item.accommodation_id} value={item}>
<Accommodation />
</AccommodationProvider>
))}
<Divider width="100%" />
</AccommodationListContainer>
);
};
데이터 공유가 필요한 컴포넌트 트리의 최상단에서 Provider 컴포넌트로 하위 컴포넌트들을 감싸준다.
const Accommodation = () => {
const accommodation = useAccommodation();
return (
<AccommodationContainer>
<AccommodationImg src={accommodation.accommodation_photo_url} />
<AccommodationInfo />
</AccommodationContainer>
);
};
위에서 구현한 커스텀 훅으로 데이터에 바로 접근할 수 있다.
Provider의 value prop이 변경되면, 해당 컨텍스트를 useContext로 구독(사용)하고 있는 모든 하위 컴포넌트가 리렌더링된다.value prop에 매번 새로운 객체를 전달하면, 부모 컴포넌트가 리렌더링될 때마다 value가 새롭게 인식되어 컨텍스트를 사용하는 모든 자식이 리렌더링된다.useMemo / useCallback: value로 전달되는 객체나 함수를 useMemo와 useCallback으로 메모이제이션하여 불필요한 재생성을 방지한다.