[리액트 네이티브] 채팅 애플리케이션 만들기 2. 내비게이션, 로그아웃, 프로필 화면
my code archive
article thumbnail
반응형

대부분의 애플리케이션은 데이터에 접근할 수 있는 유효한 사용자라는 것을 증명해야 하며, 인증 후 서비스를 이용할 수 있는 화면이 렌더링, 로그아웃 등으로 인증 상태를 해제하면 다시 인증을 위한 화면으로 이동함.


1. MainStack 내비게이션

const MainStack = () => {
    const theme = useContext(ThemeContext);

    return(
        <Stack.Navigator
            initialRouteName="Main"
            screenOptions={{
                headerTitleAlign: 'center',
                headerTintColor: theme.headerTintColor,
                cardStyle: {backgroundColor: theme.backgroundColor},
                headerBackTitleVisible: false,
            }}
        >
            <Stack.Screen name="Main" component={MainTab} />
            <Stack.Screen name="Channel Creation" component={ChannelCreation} />
            <Stack.Screen name="Channel" component={Channel} />
        </Stack.Navigator>
    );
};

export default MainStack;

MainStack 내비게이션은 채널 목록 화면, 프로필 화면으로 구성된 MainTab 내비게이션을 첫 번째 화면으로 가짐.

실행 화면

2. MainTab 내비게이션

MainTab 내비게이션을 구성하는 채널 목록 화면 ChannelList.js, 프로필 화면 Profile.js 작성

const ChannelList = ({navigation}) => {

    return(
        <Container>
            <Text style={{fontSize: 24}}>Channel List</Text>
            	<Button
                title="Channel Creation"
                onPress={() => navigation.navigate('Channel Creation')}
            />
        </Container>
    );
};

export default ChannelList;

4. 인증 & 화면 전환

로그인 혹은 회원가입을 통해 인증을 성공했을 경우, 그렇지 않을 경우 각각 다른 내비게이션이 렌더링되도록 한다.

=> Context API 이용

 

UserContext를 만들고 인증 상태에 따라 적절한 내비게이션이 렌더링되도록함.

import React, {useState, createContext} from "react";

const UserContext = createContext({
    user: {email: null, uid: null},
    dispatch: () => {},
});

const UserProvider = ({children}) => {
    const [user, setUser] = useState({});
    const dispatch = ({email, uid}) => {
        setUser({email, uid});
    };
    const value = {user, dispatch};
    return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};

export {UserContext, UserProvider};

인증되면 UserContext의 user를 수정하도록 로그인 화면 수정

5. 로그아웃

로그아웃 함수 firebase.js에 추가

//로그아웃
export const logout = async() => {
    return await authService.signOut();
};

프로필 화면에 로그아웃 버튼 생성 후 logout 함수 호출

  • logout 함수 완료 시 UserContext의 dispatch 함수를 이용해 user의 상태 변경
  • 사용자 인증과 마찬가지로 로그아웃을 통해 인증 해제 후에는 스와이프, 뒤로가기 버튼을 통해 다시 이전 내비게이션으로 돌아갈 수 없다.
const Profile = () => {
    const {dispatch} = useContext(UserContext);
    
    ...
    
    const _handleLogoutButtonPress = async () => {
        try{
            spinner.start();
            await logout();
        }catch(e){
            console.log('[Profile] logout: ',e.message);
        }finally{
            dispatch({});
            spinner.stop();
        }
    };

...
    return (
        <Container>
          <Image>
          ...
          <Button
            title="logout"
            onPress={_handleLogoutButtonPress}
            containerStyle={{backgroundColor: theme.buttonLogout}}
          />
        </Container>
      );
    };
    
    export default Profile;

실행 화면

6. 프로필 화면

현재 접속한 사용자 정보 반환 함수

//현재 접속한 사용자 정보 반환
export const getCurrentUser = () => {
    const {uid, displayName, email, photoURL} = authService.currentUser;
    return {uid, name: displayName, email, photoUrl: photoURL};
};

사용자 사진 수정 함수

//사용자 사진 수정
export const updateUserPhoto = async photoUrl => {
    const user = authService.currentUser;
    const storageUrl = photoUrl.startsWith('https')
        ? photoUrl
        : await uploadImage(photoUrl);
    await user.updateProfile({photoURL: storageUrl});
    return {name: user.displayName, email: user.email, photoUrl: user.photoURL};
};

현재 접속한 사용자 정보가 있는 currentUser에서 필요한 값을 받아오고, 스토리지에 선택된 사진을 업로드하는 함수를 이용해 사용자의 사진을 수정함.

Profile.js 수정

  • 사용자의 사진은 현재 접속한 사용자의 사진이 렌더링되도록 getCurrentUser 함수를 통해 받아온 user의 photoUrl 사용
  • getCurrentUser 함수가 반환한 내용으로 사용자의 이름, 이메일을 Input 컴포넌트로 렌더링
  • 수정할 수 없도록 disabled 추가
const _handlePhotoChange = async url => {
        try{
            spinner.start();
            const updatedUser = await updateUserPhoto(url);
            setPhotoUrl(updatedUser.photoUrl);
        }catch(e){
            Alert.alert('Photo Error',e.message);
        }finally{
            spinner.stop();
        }
    };

    return (
        <Container>
          <Image
            url={photoUrl}
            onChangeImage={_handlePhotoChange}
            showButton
            rounded
          />
          <Input label="Name" value={user.name} disabled />
          <Input label="Email" value={user.email} disabled />
          <Button
            title="logout"
            onPress={_handleLogoutButtonPress}
            containerStyle={{backgroundColor: theme.buttonLogout}}
          />
        </Container>
      );
    };
    
    export default Profile;

실행 화면

반응형
profile

my code archive

@얼레벌레 개발자👩‍💻

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

반응형