[React Native] 로그인 통신 시 사용자가 다른 행동을 못하도록 Spinner 컴포넌트 구현

cooking_123·2024년 3월 31일

React Native TIL

목록 보기
26/30

로그인하거나 회원가입 통신할때 사용자가 다른 행동을 하지 않도록 Spinner 컴포넌트를 만드려고 한다.

공식문서 : https://reactnative.dev/docs/activityindicator

  1. 먼저 components 폴더 안에 Spinner 컴포넌트를 만든다. Spinner 컴포넌트가 다른 컴포넌트보다 항상 최상위에 위치하도록 z-index: 2;를 설정해준다.

components/Spinner.js

import React from 'react';
import styled from 'styled-components/native';

const Container = styled.View`
    position: absolute;
    z-index: 2; /** 컴포넌트가 최상위에 위치하도록 */
    opacity: 0.3;
    width: 100%;
    height: 100%;
    justify-content: center;
    background-color: ${({ theme }) => theme.spinnerBackground};
`;

const Indicator = styled.ActivityIndicator.attrs(({ theme }) => ({
    size: 'large',
    color: theme.spinnerIndicator,
}))``;

const Spinner = () => {
    return (
        <Container>
            <Indicator />
        </Container>
    );
};

export default Spinner;
  1. 어떤 화면이든 다른 행동을 취하지 못하도록 navigatins의 index.js에 추가해준다.
import { NavigationContainer } from '@react-navigation/native';
import React, { useContext } from 'react';
import Auth from './Auth';
import { UserContext } from '../contexts';
import Main from './Main';
/**어떤 화면이든 가리도록 navigations의 index.js에서 스피너 컴포넌트 사용 */
import { Spinner } from '../components';

const Navigation = () => {
    const { user } = useContext(UserContext);
    return (
        <NavigationContainer>
            {user.uid ? <Main /> : <Auth />}
            <Spinner />
        </NavigationContainer>
    );
};

export default Navigation;

  1. 네트워크 통신같이 시간 지연이 있는 행동을 시작할 때 스피너 컴포넌트가 나타나고 끝나면 스피너 컴포넌트를 사라지도록 설정해주어야 하기에 Spinner 컴포넌트의 렌더링 여부를 결정하는 progremmers context 만들었다.

contexts/progress.js

//Spinner 컴포넌트의 렌더링 여부를 결정

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

const ProgressContext = createContext({
    inProgress : false,
    spinner: {start:()=>{}, stop: ()=>{}}
});

const ProgressProvider =({children}) =>{
    const [inProgress, setInProgress] = useState(false);
    const spinner ={
        start : () => setInProgress(true),
        stop : () => setInProgress(false)
    };
    const value = {inProgress, spinner}
    return (
        <ProgressContext.Provider value={value}>
            {children}
        </ProgressContext.Provider>
    )
}

export {ProgressContext, ProgressProvider}
  1. 로그인과 회원가입시 통신을 통해 통신을 시도할때 스타트르 호출하고 스탑을 호출해서 로그인을 시도

signin.js

import { UserContext, ProgressContext } from '../contexts';

const { spinner } = useContext(ProgressContext);

    const _handleSigninBtnPress = async () => {
        try {
            spinner.start();
            const user = await signin({ email, password });
            setUser(user);
        } catch (e) {
            Alert.alert('Signin Error', e.message);
        } finally {
            spinner.stop();
        }
    };

signup.js

import { UserContext, ProgressContext } from '../contexts';

const { spinner } = useContext(ProgressContext);

const _handleSignupBtnPress = async () => {
    try {
        spinner.start();
        const user = await signup({ name, email, password, photo });
        setUser(user);
    } catch (e) {
        Alert.alert('Signup Error', e.message);
    } finally {
        spinner.stop();
    }
};
  1. inProgress값에 따라 Spinner 컴포넌트가 렌더링 되도록 설정
import { NavigationContainer } from '@react-navigation/native';
import React, { useContext } from 'react';
import Auth from './Auth';
import { UserContext, ProgressContext } from '../contexts';
import Main from './Main';
import { Spinner } from '../components';

const Navigation = () => {
    const { user } = useContext(UserContext);
    const { inProgress } = useContext(ProgressContext);

    return (
        <NavigationContainer>
            {user.uid ? <Main /> : <Auth />}
            {inProgress && <Spinner />}
        </NavigationContainer>
    );
};

export default Navigation;

이렇게 코드를 작성해주니 로그인 시도시 spinner이 잘 돌아간다.

0개의 댓글