History.push는 비동기로 동작할까?

미누도 개발한다·2021년 6월 10일
0

리액트

목록 보기
4/11
post-thumbnail

history.push를 하면 그 즉시, 페이지로 이동하게되는가?

로그인/회원가입 모듈을 개발하다가 문득 위와같은 문제에 부딪혔다.
로그인/회원가입 실패시 모달을 띄워주고, 성공시 페이지 리다이렉트를 하는 모듈을 만들어야한다.

예를들어 로그인페이지(/login)에서, 로그인실패시에는 모달을 띄워주고, 성공시 홈('/')으로 간다고 가정해보자.
만약 '/login' path의 컴포넌트에 상태업데이트 스케쥴이 남아있을때, push를 통해 즉시 다른 path로 들어간다면 상태 업데이트 스케쥴을 통해 리렌더링이되야하는 컴포넌트(/login)가 사라져버릴것이다.


그렇게되면 위와같은 오류를 보게 될 것이다.

history.push는 다행히 기능적으로 비동기다.

export const useUserAuth = (reqFunction,startWithPending,isLogin) => {
    const history = useHistory();
    const reduxDispatch = useDispatch();
    const [state,dispatch] = useReducer(authReducer,{
        status:startWithPending ? 'pending': null,
        data : null,
        error: null
    });

    const sendRequest = useCallback(async(reqParams)=>{
        dispatch({type:'SEND'});

        try{
            const data = await reqFunction(reqParams,isLogin);
            reduxDispatch({type:'LOGIN',payload:{idToken:data.idToken , expiresIn:data.expiresIn , dispatch:reduxDispatch} });
            history.replace('/');

        }catch(err){
            dispatch({type:'ERROR',payload:err.message});
        }
        
    },[isLogin]);
    

코드에 대한 간단한 설명:

Dispatch가 호출되어 reduxstore 데이터가 변경되면, login컴포넌트가 리렌더링된다.

테스트 결과:

맨 위의 질문에서처럼, 만약 push,replace가 동기적 실행이라면, dispatch에 의한 리렌더링 스케줄이 남아있는상태에서 redirect가 이뤄지기 때문에, 에러로그가 뜰것이다.

dispatch가 호출되고 history.replace가 호출된 후에, dispatch에 의한 리렌더링이 일어나고,
그다음 replace가 적용되는것을 콘솔로 확인하였다.
즉, history.replace가 호출되기전에 스케쥴된 것들을 모두 처리한다음 redirect가 발생한다.

Redirect component vs history.push

1월11일 추가내용)
리액트에서 history API를 사용할때 보통 두가지 방식을 사용한다.
Redirect 컴포넌트는, 마운트 되었을 때 , history.push를 호출하도록 설계되어 있는것 같다.
history.push()를 호출한다고해서, 그 즉시, 해당 함수형 컴포넌트의 return문이 block 되는 것이 아니라, 마운트 된 다음, historyAPI가 동작한다. 따라서, 의도하지않은 의미없는 컴포넌트가 아주 순간적으로 렌더링이 되게되는데(눈에는 거의 보이지 않음), 이를 방지할 때 Redirect컴포넌트를 사용한다.
👇 참고 링크
https://stackoverflow.com/questions/48619733/react-router-redirect-vs-history-push

참고

테스팅을 끝내고 혹시나해서 스택오버플로우를 봤는데 역시 비슷한 질문이 있었다.

https://stackoverflow.com/questions/53921508/is-history-push-an-async-call-in-react

https://github.com/ReactTraining/react-router/issues/6512

profile
빨리 가는 유일한 방법은 제대로 가는 것이다

0개의 댓글

관련 채용 정보