특정 페이지에 도달 할 수 있는 링크인 딥링크를 이용하고 있다.
앱이 완전히 닫힌 상태에서 딥링크로 앱을 열면,
(Android의 경우) Linking.getInitialURL 로
(iOS의 경우) Linking.addEventListener('url', handleOpenUrl) 로
앱을 열게 한 url 장본인(?)을 알 수 있다.
(이 글은 Android 기준으로 코드를 작성했습니다.)
const url = "roubitapp://root-tab/setting"
위 url로 앱을 열면 SettingScreen이라는 화면으로 navigate해야한다고 가정해보자.
코드는 아래와 같이 짤 수 있다. (자세한 딥링크 세팅은 이곳을 참고)
import React, { useEffect, useState } from 'react';
import { Linking } from 'react-native';
import { NavigationContainer, useLinkTo } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();
export default () => {
const linkTo = useLinkTo()
useEffect(() => {
Linking.getInitialURL()?.then(url => {
if (url) {
const deepLink = getDeepLinkByUrl(url); // ex. '/setting'
linkTo(deepLink)
}
});
}, [])
return (
<NavigationContainer
linking={{
prefixes: ['roubitapp://'],
config: {
// ...,
SettingScreen: {
path: "setting"
}
}
}}
>
<Stack.Navigator>
<Stack.Screen />
<Stack.Screen />
<Stack.Screen />
</Stack.Navigator>
</NavigationContainer>
);
}
그런데, linkTo를 사용하면 아래와 같은 오류가 난다.
// ERROR The 'navigation' object hasn't been initialized yet.
// This might happen if you don't have a navigator mounted,
// or if the navigator hasn't finished mounting.
// See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details.
아직 navigation이 세팅되지 않았는데 사용하려고 해서 생기는 문제다.
에러에 친절하게 안내되어있는 링크를 따라가본다. (웬만한 에러는 에러내용 잘 읽으면 해결됨. 떠먹여주는대로 받아먹자!)
navigation이 세팅되었는지를 아는 방법에 대해 안내해준다.
하지만 Linking.getInitialURL()을 실행하는 시점에 navigationRef.isReady()가 여전히 false라면 쓰나마나다.
우리는 navigation이 세팅되는 순간을 알아야 한다. 그래야 그 이후에 linkTo를 사용할 수 있기 때문이다.
NavigationContainer에 onReady라는 prop을 사용하면 된다.
문서에서는 아래와 같이 설명하고 있다.
// Function which is called after the navigation container and all its children finish mounting for the first time.
NavigationContainer와 하위 컴포넌트가 모두 마운팅을 마친 시점에 onReady가 실행된다.
이 점을 이용하여 아래와 같이 코드를 추가했다.
import React, { useEffect, useState } from 'react';
import { Linking } from 'react-native';
import { NavigationContainer, useLinkTo } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator<RootTabStackParams>();
export default () => {
const [isNavMounted, setIsNavMounted] = useState<boolean>(false);
const linkTo = useLinkTo()
useEffect(() => {
if (isNavMounted) {
Linking.getInitialURL()?.then(url => {
if (url) {
const deepLink = getDeepLinkByUrl(url); // ex. '/setting';
linkTo(deepLink)
}
});
}
}, [isNavMounted])
return (
<NavigationContainer
onReady={() => {
setIsNavMounted(true)
}}
linking={{
prefixes: ['roubitapp://'],
config: {
// ...,
SettingScreen: {
path: "setting"
}
}
}}
>
<Stack.Navigator>
<Stack.Screen />
<Stack.Screen />
<Stack.Screen />
</Stack.Navigator>
</NavigationContainer>
);
}
이제 isNavMounted를 이용하여 navigation 세팅이 완료되었음을 확신하고 linkTo를 사용할 수 있게 되었다.🔥🔥🔥
참고링크
https://velog.io/@beanlove97/NavigationContainer
https://reactnavigation.org/docs/navigating-without-navigation-prop/#handling-initialization
https://reactnavigation.org/docs/navigation-container/#onready
'Development > React Native' 카테고리의 다른 글
react-native-push-notification 사용 시 주의점 (안드로이드 id) (0) | 2023.06.09 |
---|---|
[React Native를 활용한빠르고 완성도 높은 앱 개발with 21개 프로젝트] 강의메모 (5) | 2023.04.21 |
[ReactNative] KeyboardAvoidingView 안에 여러 TextInput을 사용할 때 offset 맞지 않는 문제 해결 (0) | 2023.02.03 |
[React Native] 가로의 길이가 바뀌는 디바이스(폴드) 대응: Dimensions -> useDimensions (0) | 2023.01.25 |
Apollo Client query 시 주의점 (variables) (0) | 2023.01.21 |