로그인 한 후 뒤로가기
로그인 한 후의 화면을 관리
Stack
Auth Stack : Sign in + List => Auth Stack과 Main Stack을 분리
AuthStack : Sgin in MainStack : List
이렇게 분리할 것.
위와 같이 분리하면
로그인 버튼 눌렀을 때,
MainStack 을 보여줘야하므로 이동할 수 없음.
MainStack으로 이동하기
- MainStack 만들기
import { Pressable, Text } from 'react-native';
import { PRIMARY, WHITE } from '../colors';
import ListScreen from '../screens/ListScreen';
import { useNavigation } from '@react-navigation/native';
import HeaderLeftButton from '../components/HeaderLeftButton';
import HeaderRightButton from '../components/HeaderRightButton';
import SettingsScreen from '../screens/SettingsScreen';
const {
createNativeStackNavigator,
} = require('@react-navigation/native-stack');
const Stack = createNativeStackNavigator();
const MainStack = () => {
return (
<Stack.Navigator
initialRouteName="List"
screenOptions={{
contentStyle: {
backgroundColor: WHITE,
},
headerTitleAlign: 'center',
headerTintColor: PRIMARY.DEFAULT,
headerTitleStyle: {
fontWeight: '700',
},
headerBackTitleVisible: false,
headerLeft: HeaderLeftButton,
}}
>
<Stack.Screen
name={'List'}
component={ListScreen}
options={{
title: 'ToDo List',
headerRight: HeaderRightButton,
}}
/>
<Stack.Screen name={'Settings'} component={SettingsScreen} />
</Stack.Navigator>
);
};
export default MainStack;
- AuthStack 정리하기
import { PRIMARY, WHITE } from '../colors';
import SignInScreen from '../screens/SigninScreen';
const {
createNativeStackNavigator,
} = require('@react-navigation/native-stack');
const Stack = createNativeStackNavigator();
const AuthStack = props => {
return (
<Stack.Navigator
initialRouteName="SignIn"
screenOptions={{
contentStyle: {
backgroundColor: WHITE,
},
}}
>
<Stack.Screen
name={'SignIn'}
options={{
headerShown: false,
}}
>
{/* screenProps안에는 navigation 과 route 정보가 있음 */}
{screenProps => (
<SignInScreen {...screenProps} {...props}></SignInScreen>
)}
</Stack.Screen>
</Stack.Navigator>
);
};
export default AuthStack;
위와 같이한 후
- App.js 에서 Stack 관리
const App = () => {
const [user, setUser] = useState(null);
return (
<NavigationContainer>
<StatusBar style="dark" />
{user ? <MainStack /> : <AuthStack setUser={setUser} />}
</NavigationContainer>
);
};
user라는 state를 만들어서 그에 맞게 stack 교체
여기서 setUser 메서드를 props로 전달
이를 SignIn 까지 보내야하는데..
계속 전달전달해야 함… 불편..
PropDrilling
전달의 전달 전달…
전역변수의 상태 관리
ContextAPI 를 사용하면 된다.
Context 만들기 (userContext.js)
const { createContext } = require('react');
const UserContext = createContext();
export default UserContext;
App.js 에서 UserContext로 감싸기
<UserContext.Provider value={{ setUser }}>
<NavigationContainer>
<StatusBar style="dark" />
{user ? <MainStack /> : <AuthStack />}
</NavigationContainer>
</UserContext.Provider>
위와 같이 감싸면 value를 통해서 공유할 수 있다.
이를 Signin 컴포넌트를 감싸면
return (
<UserContext.Consumer>
{({ setUser }) => {
return (
<SafeInputView>
<View
style={[
styles.container,
{
paddingTop: insets.top,
paddingBottom: insets.bottom,
},
]}
>
<Image
source={require('../../assets/main.png')}
style={styles.image}
resizeMode="cover"
></Image>
<Input
value={email}
onChangeText={text => setEmail(text.trim())}
title={'email'}
placeholder={'your@email.com'}
keyboardType={KeyboardTypes.EMAIL}
returnkeyType={ReturnkeyTypes.NEXT}
iconName={IconNames.EMAIL}
onSubmitEditing={() => passwordRef.current.focus()}
multiline={false}
></Input>
<Input
ref={passwordRef}
value={password}
onChangeText={text => setPassword(text.trim())}
title={'password'}
placeholder={''}
secureTextEntry
iconName={IconNames.PASSWORD}
onSubmitEditing={() => {
onSubmit(setUser);
}}
></Input>
<View style={styles.buttonContainer}>
<Button
title={'LOGIN'}
onPress={() => {
onSubmit(setUser);
}}
disabled={disabled}
isLoading={isLoading}
></Button>
</View>
</View>
</SafeInputView>
);
}}
</UserContext.Consumer>
);
setUser 를 받아올 수 있고 이를 Submit에 변수로 넘겨서 실행시켜주면 된다.
흠.. 이게 편한가??? 난 솔직히 불편해보임…
만들고, 감싸고, 등등..
두개이상 만들어야 하면 어떻게함??
useContext
const { setUser } = useContext(UserContext);
위를 통해 접근하면 어디서나 접근할 수 있고 감싸줄 필요도 없음 (최초에 Provider는 감싸줘야함.)
일단 코드를 정리해준다.
export const userUserContext = () => useContext(UserContext);
vscode 에 사용하면 좋은 기능
{
// Place your GLOBAL snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
"Function Component with PropTypes": {
"scope": "javascript",
"prefix": "fcpt",
"body": ["console.log('$1');", ""],
"description": "Create Function Component with PropTypes"
}
}