[React Native] Navigation Basics - Screen 외부 컴포넌트에서 navigation 사용하기
Nadan Dev Blog
React Navigation Screen 외부 컴포넌트에서 사용하기
원래는 navigation이 screen 기본 prop으로 전달되는데, screen 내부 컴포넌트에서 해당 navigation 기능을 사용해야 하는 경우가 있다. 예를 들어, navigation link를 컴포넌트화 해서 분리했을 경우, onPress 함수로 navigation.navigate()를 호출해야 할 것이다. 이 경우 navigation을 전달받아야 하는데, 만약 screen에서 전달받는다면, 정작 screen은 사용하지 않는데 중간 레이어이기 때문에 navigation을 가지고 있다면 코드가 스파게티가 된다. 관리도 어렵고.
react native에서 직접 전달받아 사용할 수 있음.
Opt1) withNavigation 활용
import { withNavigation } from 'react-navigation';
const ResultsList = ({ navigation }) => {
...
}
export default withNavigation(ResultsList);
예시) NavLink.js
NavLink.js
import React from 'react';
import { Text, TouchableOpacity, StyleSheet } from 'react-native';
import Spacer from './Spacer';
import { withNavigation } from 'react-navigation';
const NavLink = ({ navigation, text, routeName }) => {
return (
<Spacer>
<TouchableOpacity onPress={() => navigation.navigate(routeName)}>
<Text style={styles.link}>{text}</Text>
</TouchableOpacity>
</Spacer>
)
}
const styles = StyleSheet.create({
link: {
color: 'blue'
}
});
export default withNavigation(NavLink);
SignUpScreen.js
import NavLink from '../components/NavLink';
const SignUpScreen = ({ navigation }) => {
const { state, signup } = useContext(AuthContext);
return (
<View style={styles.container}>
<NavLink
routeName="SignIn"
text="Already have an account? Sign in instead"
/>
</View>
);
}
Opt2) navigationRef 활용
-> 컨벤션으로 활용되는 코드인지 확인
withNavigation은 하나의 컴포넌트 자체를 withNavigation로 감쌀 수 있는 경우 사용할 수 있다. 보통의 경우 컴포넌트를 분리할 때 하나의 함수를 export 하는데, 이 전체를 withNavigation으로 감싸주고, navigation을 prop으로 받는 것이다.
만약 하나로 감쌀 수 없는데 필요한 경우 navigationRef 활용한다. context의 경우 하나의 함수가 아니라 reducer 포함 여러 action 함수들이 있기 때문에 action에서 navigation을 사용하기 위해서는 바로 navigate 할 수 있는 함수가 필요함.
navigationRef.js
import { NavigationActions } from 'react-navigation';
let navigator;
export const setNavigator = (nav) => {
navigator = nav;
};
export const navigate = (routeName, params) => {
navigator.dispatch(
NavigationActions.navigate({
routeName, params
})
);
};
App.js
import { setNavigator } from './src/navigationRef';
...
export default () => {
return (
<AuthProvider>
<App ref={(navigator) => { setNavigator(navigator) }}/>
</AuthProvider>
)
}
AuthContext.js
import { navigate } from '../navigationRef';
...
const signup = (dispatch) => {
return async ({ email, password }) => {
try {
const response = await trackerAPI.post('/signup', { email, password })
await AsyncStorage.setItem('token', response.data.token);
dispatch({ type: 'signup', payload: response.data.token })
navigate('TrackList')
} catch (err) {
dispatch({ type: 'add_error', payload: 'Something went wrong with sign up'});
}
}
}