seminar-2022
seminar-2022 copied to clipboard
React 세미나2 url 변경 시 context 값이 초기화되는 현상에 관한 질문
안녕하세요. 세미나2 과제 관련해서 구글 검색을 해도 방법을 찾지 못해 질문드립니다.
URL을 변경하면, 기존의 메뉴와 로그인 context가 초기화되는 문제입니다. 예를 들면 아래와 같습니다.
- 로그인한 상태에서 URL을 통해 이동하고자
menus/4
를 입력하면 로그인 상태가 해제됩니다. - 메뉴를 추가한 뒤, 추가된 메뉴를 보고자 URL에
stores/1
를 입력하면 기본 메뉴만 남아있습니다.
헤더를 비롯한 각 컴포넌트 내의 Link
를 이용하여 이동할 때는 이러한 문제가 발생하지 않습니다.
현재 제 App 컴포넌트는 대략 아래와 같습니다. (과제 수행과 관련하여 문제되는 부분이 있다면 수정하겠습니다)
... // data.json을 data로 import한 상태
function App() {
const [menuItems, setMenuItems] = useState(data);
const [loginObj, setLoginObj] = useState({
isLogin: false,
id: "",
password: "",
});
return (
<div>
<SessionContext.Provider value={{ loginObj, setLoginObj }}> // SessionContext.js 파일을 import한 상태
<MenuDataContext.Provider value={{ menuItems, setMenuItems }}> // MenuDataContext.js 파일을 import한 상태
<BrowserRouter>
<Routes>
... // Route 들
</Routes>
</BrowserRouter>
</MenuDataContext.Provider>
</SessionContext.Provider>
</div>
});
문제가 발생한 이유를 파악하기 위해 이 App 컴포넌트의 return 문 위에 console.log를 입력해보았는데, URL을 바꿔 입력할 때마다 콘솔에 찍혔습니다. 이를 통해 App의 useState
를 이용한 부분 역시 URL이 바뀌어 입력될 때마다 새로 실행되고, 이 때문에 menuItems
와 loginObj
역시 초기화되는 것이라고 생각하였습니다. 그러나 이후에 어떻게 이 문제를 해결해야할지에 대한 방법을 찾지 못하고 있습니다. 혹시 이와 관련하여 도움 주신다면 정말 감사하겠습니다!
react-router가 제공하는 Link와 navigate 등을 통해 링크를 바꾸는 경우, 일반적인 a 태그처럼 새로 페이지를 불러오는 것이 아니라 주소값만 바꾸어 새로 렌더링하게 됩니다. 하지만 주소창을 직접 수정하여 이동하는 경우 기본적으로 모든 HTML+CSS+JS를 서버에서 새로 불러오게 됩니다. 새로고침할 때처럼 내부적으로 저장되어있던 useState나 context의 모든 상태들도 초기화되는 것이 당연합니다.
이를 막으려면 로컬스토리지나 쿠키에 필요한 값을 저장하여 페이지 전환 간에도 상태를 유지할 수 있습니다. 이번 과제에서 해당 부분은 채점하지 않겠지만 연습 삼아 해보시는 것도 괜찮을 것 같습니다. setLoginObj
를 그대로 넘기 않고 스토리지에 저장하도록 persistLoginObj
로 한번 감싸서 provider의 value로 넣어줄 수 있겠습니다.
useEffect(() => {
const storedLoginObj = localStorage.getItem("loginObj"));
setLoginObj(JSON.parse(storedLoginObj));
}, []); // 빈 dependency array를 설정하면 마운트될 때 한번만 실행됩니다.
function persistLoginObj(newLoginObj) {
setLoginObj(newLoginObj);
localStorage.setItem("loginObj", JSON.stringify(newLoginObj));
}
답변 감사합니다! context를 사용하는 게 처음이다보니 서툴러서 발생한 문제인 줄 알았는데, 당연한 것이었군요. 로컬 스토리지를 이용하는 코드도 첨부해주셔서 감사합니다. 참고하여 관련된 부분 찾아보고, 코드에도 반영해보겠습니다!(아마 다음 과제에..)