const hiddenPath = ['/login', '/signup'];
function Layout() {
const { pathname } = useLocation();
const [isHiddenPath, setIsHiddenPath] = useState(
hiddenPath.includes(pathname),
);
useEffect(() => {
setIsHiddenPath(hiddenPath.includes(pathname));
}, [pathname]);
return (
...
<MainContainer isHiddenPath={isHiddenPath}>
...
)
}
모든 페이지에서 공통적으로 사용하는 Layout
컴포넌트의 코드다.
footer
, Nav
, margin
값이 없어야 하는 path를 hiddenPath
라는 배열에 담아 두었다.
그리고 현재 위치한 pathname
이 hiddenPath
배열에 포함되었는 지를 확인하는 isHiddenPath
상태에 따라 동적으로 스타일링하여 margin
값을 변경하였다.
이렇게 코드를 작성하고나니, 메인 페이지에서 로그인 페이지로 이동할 때 묘하게 눈이 아픈 것 같고... 뭔가 화면이 깜빡이는 것 같았다.
너무 찰나여서 동영상으로 녹화해서 천천히 돌려보니
margin
이 들어가 있는 메인페이지에서 margin
이 없는 로그인 페이지로 이동할 때
이전의 margin
값이 아주 잠~시!! 남아 있다가 margin
이 사라지는 것을 확인하였다.
원인은 useEffect
였다!
useEffect
는 브라우저가 업데이트된 화면을 먼저 렌더링한 후 즉, 레이아웃 작업과 리페인트 작업이 끝난 후에 비동기적으로 실행된다.
페이지 이동으로 인해 새로운 DOM을 생성하여 화면에 렌더링하고 나서야, useEffect
에 전달한 상태 변경 함수가 실행되면서 isHiddenPath
상태가 바뀌고, 그에 따라 margin
값이 바뀌기 때문에 잠시 예전의 margin
이 남아있는 것이었다!
If your Effect wasn’t caused by an interaction (like a click), React will let the browser paint the updated screen first before running your Effect. If your Effect is doing something visual (for example, positioning a tooltip), and the delay is noticeable (for example, it flickers), replace useEffect with useLayoutEffect.
리액트 공식문서에 따르면 리액트는 effect를 실행하기 전에 업데이트된 화면을 먼저 페인트하게 되는데, 이때 깜빡임과 같은 지연이 눈에 띄는 경우에는 useEffect
를 useLayoutEffect
로 대체하라고 한다.
useLayoutEffect는 브라우저가 화면을 리페인트하기 전에 동기적으로 실행되는 useEffect다.
useLayoutEffect
를 사용하면
DOM 생성 → `useLayoutEffect` 실행 → 상태 변경에 따라 margin 값 변경 → 리페인트
순으로 진행되기 때문에 margin
값 변경으로 인한 깜빡임이 화면에 나타나지 않게 된다!
const hiddenPath = ['/login', '/signup'];
function Layout() {
const { pathname } = useLocation();
const [isHiddenPath, setIsHiddenPath] = useState(
hiddenPath.includes(pathname),
);
useLayoutEffect(() => {
setIsHiddenPath(hiddenPath.includes(pathname));
}, [pathname]);
return (
...
<MainContainer isHiddenPath={isHiddenPath}>
...
)
}
이렇게 보니 useLayoutEffect
가 useEffect
보다 훨씬 좋아보이지만, useLayoutEffect
는 성능 저하를 일으킬 수 있기 때문에 가능하면 useEffect
를 사용해야 한다고 한다~
예전 같으면 페이지 이동할 때 깜빡이는 줄도 몰랐을 것 같은데
확실히 리팩터링을 하다보니 조금 더 세세하게 사이트를 뜯어보게 되는 것 같다!!
완~~전 미세한 차이지만 요런 미세한 차이들이 모여서 좋은 UI/UX를 만드는 것이 아닌가 싶다~ 🥳