-
<TIL> redux 적용 로그인 인증 화면 만들기 - Trello(7)TIL 2020. 4. 13. 16:24
한동안 바빠 1일1커밋 지키지 못하였다...로그인 인증 하는 부분에서 return 안에 인증하는 함수를 실행시켰더니 함수가 계속 작동되는 비효율적인 인증 방법이 실행이 되었습니다.
이러한 부분을 Redux 적용하여 훨씬 간단하게 인증할 수 있게 구현 하였습니다.1. Reducer, action 함수 만들기
일단 그러면 redux에 action의 타입과 action 함수를 만들어 줍니다.
redux를 사용할 component에서 action함수를 꺼내 사용해야 하기 때문에 export를 앞에 넣어 줘야 합니다.
export const SaveToken = 'SAVETOKEN'; // 액션 타입 정의 export const saveTokenInStore = () => ({ type: SaveToken });
그러한 다음 state기본 값은 initalTokenStore으로 지정해 주고 state의 값을 변경해주는 Reducer을 만들어 줍니다.
Reducer의 역할은 action함수가 실행이 되면 action의 type에 맞는 state로 값을 변경해주는 일을 합니다.
const initalTokenStore = { SavetokenInStorage: false, }; export default function State(state = initalTokenStore, action) { switch (action.type) { case SaveToken: return { SavetokenInStorage: true, }; default: return state; } }
2.Store 만들기
Provider를 이용한 component에서 connect를 사용할 수 없기 때문에 App.js에서 라우터를 관리하던 것을 두개의 component로 쪼개 버렸습니다.
App.js에서는 provider를 이용하여 Store를 적용하는 일만 하고
import { createStore } from 'redux'; import React, { Component } from 'react'; import { Provider } from 'react-redux'; import Nav from './Nav'; import Reducer from './components/Redux/Reducer'; const store = createStore(Reducer); class App extends Component { render() { return ( <Provider store={store}> <Nav /> </Provider> ); } } export default App;
Nav.js에서는 navigation이용하여 라우터를 구현 하고 connect를 적용하여 component에 login이 되었는지 체크 didmount로 AsyncStorage에 값의 유무를 확인하여 자동 로그인을 할 수 있게 만들었습니다
import React, { Component } from 'react'; import { connect } from 'react-redux'; import 'react-native-gesture-handler'; import { AsyncStorage } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import { createDrawerNavigator } from '@react-navigation/drawer'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { saveTokenInStore } from './Redux/Reducer'; components ...; const Stack = createStackNavigator(); const Drawer = createDrawerNavigator(); function StackBoard() { return ( <Stack.Navigator> <Stack.Screen name="Boards" component={Board} options={{ title: 'Boards' }} /> <Stack.Screen name="InBoard" component={InBord} /> <Stack.Screen name="MakeBoard" component={MakeBoard} options={{ title: 'MakeBoard' }} /> <Stack.Screen name="MakeCard" component={MakeCard} options={{ title: 'MakeCard' }} /> <Stack.Screen name="MakeContainer" component={MakeContainer} options={{ title: 'MakeContainer' }} /> <Stack.Screen name="Containers" component={Containers} /> </Stack.Navigator> ); } class Nav extends Component { constructor() { super(); this.state = { Login: false, }; } async componentDidMount() { if (await AsyncStorage.getItem('user_Token')) { this.props.loginCheck(); } } render() { return ( <NavigationContainer> <SafeAreaProvider> { this.props.Login ? ( <Drawer.Navigator> <Drawer.Screen name="Home" component={Home} options={{ title: 'Home' }} /> <Drawer.Screen name="Boards" component={StackBoard} /> <Drawer.Screen name="UserInfo" component={UserPage} /> </Drawer.Navigator> ) : ( <Stack.Navigator screenOptions={{ headerShown: false, }}> <> <Stack.Screen name="First Screen" component={First} /> <Stack.Screen name="Signup Screen" component={Signup} /> <Stack.Screen name="Login Screen" component={Login} /> </> </Stack.Navigator> )} </SafeAreaProvider> </NavigationContainer> ); } } const mapStateToProps = ({ SavetokenInStorage }) => ({ Login: SavetokenInStorage, }); const mapDispatchToProps = (dispatch) => ({ loginCheck: () => { dispatch(saveTokenInStore()); }, }); export default connect(mapStateToProps, mapDispatchToProps)(Nav);
3. login 화면에 적용
import React, { Component } from 'react'; ... import { saveTokenInStore } from '../Redux/Reducer'; class Login extends Component { constructor(props) { super(props); this.state = { password: null, email: null, loginFailAlert: false, successAlert: false, }; this.serverConnect = this.serverConnect.bind(this); } serverConnect() { const { email, password } = this.state; if (this.state.email === null || this.state.password === null) { this.setState({ loginFailAlert: true, }); } else { axios.post(`${server}/user/login`, { email, password }) .then(async (res) => { if (res.status === 201) { await AsyncStorage.setItem('user_Token', res.data.token); this.props.loginCheck(); } else { this.setState({ errAlert: false, }); } }); } } render() { return ( <View style={styles.total}> <View style={styles.AppName}> <Text style={{ fontSize: 50 }}> Hi! </Text> </View> <View style={styles.Inputs}> <Isao label="Email" style={{ width: 330, marginTop: 15 }} activeColor="#da7071" borderHeight={8} inputPadding={16} labelHeight={24} passiveColor="black" onChangeText={(text) => this.setState({ email: text })} /> <Isao label="Password" style={{ width: 330, marginBottom: 10 }} activeColor="#da7071" borderHeight={8} inputPadding={16} labelHeight={24} passiveColor="black" onChangeText={(text) => this.setState({ password: text })} /> <View style={{ flexDirection: 'row' }}> <Button title="로그인" type="outline" buttonStyle={{ width: 90, height: 40 }} onPress={this.serverConnect} /> <TouchableOpacity onPress={() => this.props.navigation.navigate('Signup Screen')}> <Text> 회원가입 </Text> </TouchableOpacity> </View> <Alert show={this.state.loginFailAlert} title="로그인 실패" message="로그인에 실패하였습니다." confirmText="로그인 다시 하기" onConfirmPressed={() => this.setState({ loginFailAlert: false, email: null, password: null, })} /> </View> </View> ); } } const styles = StyleSheet.create({ ... }); const mapDispatchToProps = (dispatch) => ({ loginCheck: () => { dispatch(saveTokenInStore()); }, }); export default connect(null, mapDispatchToProps)(Login);
'react-redux' 의 connect를 이용하여 컴포넌트에 props에 loginCheck라는 함수로 action함수를 넘겨 줍니다.
로그인이 성공하면 AsyncStorage에 토큰 값이 저장이 되고 action함수가 실행이 되면서 store의 값도 saveTokenInStorage의 값도 true로 변경이 됩니다.
'TIL' 카테고리의 다른 글
<TIL> React-Navigation header 꾸미기 - Trello(9) (0) 2020.04.24 <TIL> React -Native LongPress 구현 - Trello(8) (0) 2020.04.16 <TIL> axios 사용 중에 있었던 일- Trello(6) (0) 2020.03.23 <TIL> React-Native 로그인 플로우, 중첩 router - Trello(5) (0) 2020.03.20 <TIL> 로그인, 회원가입 화면 구현 - Trello(4) (0) 2020.03.19