- 해당 내용은 React Native를 개발하면서 작성했으나 React에도 똑같이 적용할 수 있는 내용
- useContext example
필자가 React Native를 이용해서 현재 위치를 기반으로 리스트의 각 아이템별로 데이터를 업데이트 해줘야하는 상황이었다.
단순히 각 아이템 마다 위치정보를 구독하고 계산해서 업데이트하려니 상당히 지저분하고 여러개가 구독하고 있는 괴상한 구조가 되었다.
목표는 단일 구독으로 전체 앱에서 위치정보를 공유할 수 있도록 하는 것.
하루종일 헛짓하다가 시도한 방법은 아래와 같다.
1. useLocation이라는 hook을 만들기
-> 코드만 분리될 뿐 실상은 똑같다.
2. hook을 싱글톤 처럼 쓰기
-> 그냥 실패. 될리가 없었다....
3. Redux로 관리
-> 구독 관리 및 callback 다루기 실패
최종적으로 성공한 것은
useContext를 활용한 Provider 만들기.
1. LocationContext 만들기
LocationContext를 만들고 위치 정보를 구독해서 값을 업데이트해줄 Component인 LocationProvider를 만든다.
LocationContext의 Provider는 LocationProvider 내에 들어가고 그 내부에 children을 넣어 자식 요소가 다 적용되도록 한다.
또한 useLocationContext를 작성하여 쉽고 사용하며 코드가 헷갈리지 않게 한다. (useContext(~~~) 를 여러번 쓰는걸 싫어한다.)
// LocationContext.tsx
import React, { useContext } from 'react';
import RNLocation, { Location, Subscription } from 'react-native-location';
export interface LocationContextState {
location: Location | null;
}
const initialState = {
location: null,
};
export const LocationContext = React.createContext<LocationContextState>({
location: null,
});
export const useLocationContext = () => useContext(LocationContext);
let unsubscribe: Subscription;
const LocationProvider: React.FC = ({ children }) => {
const [state, setState] = React.useState<LocationContextState>(initialState);
React.useEffect(() => {
RNLocation.configure({
distanceFilter: 5.0,
});
RNLocation.requestPermission({
ios: 'whenInUse',
android: {
detail: 'fine',
rationale: {
title: 'Location permission',
message: 'We use your location to demo the library',
buttonPositive: 'OK',
buttonNegative: 'Cancel',
},
},
}).then(granted => {
if (granted) {
unsubscribe = RNLocation.subscribeToLocationUpdates(locations => {
setState({ location: locations[0] });
});
}
});
return () => {
unsubscribe && unsubscribe();
};
}, []);
return (
<LocationContext.Provider value={state}>
{children}
</LocationContext.Provider>
);
};
export default LocationProvider;
2. App.js에서 최상위 부모에게 LocationProvider 적용
// App.js
export default () => (
<LocationProvider>
<App />
</LocationProvider>
);
3. 위치 정보를 사용할 곳에서 useLocationContext 호출
// ShopListItem.tsx
const ShopListItem: React.FC<ShopListItemProps> = ({ item }) => {
const locationContext = useLocationContext();
return (
<Text>
{locationContext.location?.longitude},{' '}
{locationContext.location?.latitude}
</Text>
);
};
반응형
'Develop > React Native' 카테고리의 다른 글
[React Native] 이미지 성능 이슈 (0) | 2021.10.05 |
---|---|
[React Native] iOS Build Error On M1 Chip (0) | 2021.03.25 |
[React Native] How to fix pod install error with missing compatible arch (0) | 2021.03.24 |
Crash with "EMFILE: too many open files, watch..." (0) | 2021.03.23 |