App.js에서 시작하자마자 로그인 여부를 확인하려고 App 파일에 코드를 전부 작성했습니다.
const AuthContext = createContext(null);
export default function App() {
const [state, dispatch] = useReducer(
(prevState, action) => {
switch (action.type) {
case "SET_TOKEN":
return {
...prevState,
token: action.token,
};
}
},
{
// isLoading: true,
token: null,
loginFailed: false,
}
);
const authMethods = useMemo(
() => ({
signIn: async (email: string, password: string) => {
try {
// 로그인 요청 해서 토큰 받기
const { token } = await login(email, password);
// 비밀 저장소에 토큰 저장
await SecureStore.setItemAsync("access_token", token);
// state의 토큰 변경
dispatch({ type: "SET_TOKEN", token });
} catch (err) {
// 토큰이 안 왔으면 = 로그인 성공 못 함
}
},
signUp: async (email: string, password: string, nickname: string) => {},
}),
[]
);
useEffect(() => {
const get_saved_token = async () => {
try {
const token = await SecureStore.getItemAsync("access_token");
dispatch({ type: "SET_TOKEN", token });
} catch (e) {
// 저장된 토큰이 없을 시
}
};
get_saved_token();
return () => {
// 앱 종료 시 state에서 토큰 제거
dispatch({ type: "SET_TOKEN", token: null });
};
}, []);
return (
<AuthContext.Provider value={authMethods}>
<NavigationContainer>
{state.token == null ? <Auth /> : <Main />}
</NavigationContainer>
</AuthContext.Provider>
);
}
하지만 warning을 만나게 됩니다.
Require cycle: App.tsx -> navigations\AuthStack.tsx -> screens\SignInScreen.tsx -> App.tsx
로그인 화면을 띄워주는 파일에서 이 부분이 문제였습니다. App에서부터 렌더링하기 시작했는데 App을 또 import 하고 있었으니까 문제가 됐던 겁니다.
import { AuthContext } from "../App";
import React, { useState, useEffect, useContext } from "react";
import { View, Button } from "react-native";
import { TextInput } from "react-native-gesture-handler";
import { AuthContext } from "../App";
const SignInScreen = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const { signIn } = useContext(AuthContext);
return (
<View>
<TextInput placeholder="이메일" value={email} onChangeText={setEmail} />
<TextInput
placeholder="비밀번호"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button title="로그인" onPress={signIn(email, password)} />
</View>
);
};
export default SignInScreen;
그럼 이제 context를 App이 아닌 다른 파일로 옮겨야 하겠죠?
그래서 저는 createContext 함수만 다른 파일로 옮겨보기로 합니다. hook는 함수형 컴포넌트 안에서만 사용할 수 있기 때문에 리듀서 함수, useMemo를 사용하는 context 디폴트 값은 옮기는 게 불가능해 보였습니다.
AuthContext.ts
import { createContext } from "react";
const AuthContext = createContext(null);
export default AuthContext;
이제 warning 없는 화면을 보실 수 있습니다.