프로젝트의 UI를 구상하며 웹에 사용할 색상을 정하던 중 예전부터 적용해보고 싶었던 다크 모드를 구현하게 되었다.
전역 관리 방법을 생각해보며 redux, recoil 등의 선택지도 있었지만 전역으로 관리할 값이 크게 많지 않을 것이라 생각하여 React 내장 기본 hook인 useContext
를 사용해보기로 했다.
추가적으로 다크 모드에서는 모드의 상태와 theme 값이 정해져 있는 값으로 토글 되는 기능 밖에 존재하지 않아 useReducer는 사용하지 않고 useState
로 간단하게 토글 로직을 구현했다.
다크 모드를 적용하면서 만났던 오류들과 해결 방법이다.
state는 변경되지만 스타일이 바뀌지 않는 문제, 재랜더링 후 초기 값이 보이는 문제
문제: 브라우저의 개발자 도구에서는 context의 변경이 확인되었지만 스타일이 변경되지 않았고 새로 고침이 되어야 모드 값에 따른 스타일이 적용되었고 추가적으로 재랜더링되고 잠깐 초기 값 스타일이 보이는 문제가 발생.
해결: theme 값을 자바스크립트 변수가 아닌 state에 저장해서 관리
하는 방식으로 변경, useEffect에서 useLayoutEffect
로 변경.
useLayoutEffect: 브라우저가 레이아웃을 계산하고 그리기 직전에 실행
2차 완성 코드
모드 전환 시 랜더링이 불필요하게 두 번 되는 문제
문제: 개발자 도구의 콘솔에서 불필요한 랜더링 2배로 발생. twilightTheme 객체는 DarkModeContext.Provider 컴포넌트가 렌더링될 때마다 새로운 객체로 생성된다. 이로 인해 다크모드 전환 시마다 새로운 객체가 만들어지면서 불필요한 렌더링이 발생.
해결: useMemo
를 사용하여 twilightTheme 객체를 메모이제이션하여 isDarkMode
값이 변경될 때만 새로운 객체를 생성하도록 수정.