로그인 한 후 뒤로가기

로그인 한 후의 화면을 관리

Stack

Auth Stack : Sign in + List => Auth Stack과 Main Stack을 분리

AuthStack : Sgin in MainStack : List

이렇게 분리할 것.

위와 같이 분리하면

로그인 버튼 눌렀을 때,

MainStack 을 보여줘야하므로 이동할 수 없음.

MainStack으로 이동하기

  1. 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;
  1. 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;

위와 같이한 후

  1. 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"
	}
}