본문 바로가기

React

[React Hooks] useEffect와 useSelector 같이 쓸 때 주의해야 할 렌더링 순서

반응형

 

이미지 출처: https://learn.habilelabs.io/what-are-component-lifecycle-methods-in-react-js-5269aaa37046

 

 

 

 

 

 

 

 

안녕하세요 주갬입니다. 

회사에서 리액트로 프로젝트를 하고 있는데 캐시를 지우고 사이트를 열면 렌더링이 제대로 되지 않는 오류를 발견했습니다. 

 

 

문제 상황)

 

 

렌더링에 문제가 발생한 hook은 다음과 같습니다. 

 

 

    const tk = useSelector(state => state.user.tk);
    const uuid = useSelector(state => state.user.uuid);
    const ogc = useSelector(state => state.user.ogc);    
    
    useEffect(() => {
  
            var data = JSON.stringify({
                "tk" : tk,
                "uuid" : uuid,
                "ogc" : ogc
            });

            var config = {
            method: 'post',
            url: ~~~~ ,
            headers: { 
                'Content-Type': 'application/json'
            },
            data : data
            };
    
            axios(config)
            .then( (response) => {
                ~~~~~~~~~~
            })
            .catch((error) => {
                console.log(error);
            });
           
    }, []);

 

렌더링 전에 이 useEffect hook을 실행해서 api를 호출해 받은 response 값을 초기 화면에 뿌려줘야했습니다.

따라서 해당 array는 처음 마운트 되어 렌더링 될 때만 호출하여 저장하면 되는 것이였으므로 useEffect의 파라미터로 빈 배열 []를 활용했었습니다.

 

https://bamtory29.tistory.com/entry/Hooks-useEffect

 

[React] Hooks - useEffect

1. useEffect useEffect는 컴포넌트가 렌더링될 때마다 특정 작업을 하도록 만드는 Hook입니다. 라이프 사이클 메소드인 componentDidMount나 componentDidUpdate, componentWillUnmount와 비슷하게 작동합니다...

bamtory29.tistory.com

 

 

문제는 요청 페이로드로 redux에 저장된 값을 보내줘야한다는 것이였습니다. 처음에는 별 생각없이 redux로 저장된 데이터를 useSelector로 가져와 넣어주었었지만 이렇게 하니

 

1. 캐시를 지우고 처음 띄우면 렌더링에 오류가 나고 

2. 그 상태에서 한번 더 새로고침하면 렌더링이 문제 없이 되는 현상이 발생했습니다.

 

 

이러한 특징으로 유추해봤을 때 react lifecycle을 내가 제대로 이해하지 못하여 렌더링 순서에 문제가 생긴 것이라고 생각했습니다.

그래서 우선 useSelector의 호출 시점을 찾아보았습니다.

 

https://bgpark.tistory.com/124

 

useSelector 호출 시점

React-Redux의 useSelector 를 사용하면서 상태변경 시점에 대해 이론만 이해한 것 같은데 실전에 적용하지 못했습니다. 계속 문제가 발생하기에 잊지않으려 사례를 공유합니다. 문제점 React를 사용하

bgpark.tistory.com

 

결론적으로 useSelector는 함수 컴포넌트 렌더링 이후에 호출이 되는 함수였습니다. 그래서 useEffect로 렌더링 되기 전에 useSelector로 받아오는 값을 사용하려고 하니 값이 제대로 들어가지 않아 api를 post 할 때 오류가 나는 것이였죠.

(새로고침을 하면 됐던 이유는 useSelector 함수가 이미 실행된 상태기 때문에 값이 저장되어 있었기 때문인 것으로 보입니다. - 정확하지 않음)

 


 

해결) 

 

 

문제를 알았으니  useEffect 업데이트 기능을 이용하여 해결을 해봐야겠다고 생각했습니다.

 

    const tk = useSelector(state => state.user.tk);
    const uuid = useSelector(state => state.user.uuid);
    const ogc = useSelector(state => state.user.ogc);    
    
    useEffect(() => {
  
            var data = JSON.stringify({
                "tk" : tk,
                "uuid" : uuid,
                "ogc" : ogc
            });

            var config = {
            method: 'post',
            url: ~~~~ ,
            headers: { 
                'Content-Type': 'application/json'
            },
            data : data
            };
    
            axios(config)
            .then( (response) => {
                ~~~~~~~~~~
            })
            .catch((error) => {
                console.log(error);
            });
           
    }, [ tk, uuid, ogc]);

 

이렇게 useEffect의 괄호[]안에 tk, uuid, ogc을 넣어주면 tk, uuid, ogc에 값이 update될 때마다 렌더링이 다시 됩니다. 그러면 마지막 값 update후에는 api에 데이터가 완전하게 전달이 될 것이고 제대로 된 response가 나올 것입니다. 최종적으로 그 response를 이용해 값을 뿌려주니 오류없이 원하는 대로 렌더링이 된 화면을 볼 수 있었습니다~!

 

 

간단한 팁이지만 React는 렌더링 주기를 확실히 신경써야겠다는 생각을 다시금 하게 되었습니다.

 

 

읽어주셔서 감사합니다!

 

 

반응형