💥 react 초보의 삽질이 가득한 글입니다. 진짜 무한루프 문제를 해결하고 싶으신 분은 다른 글을 보시는 걸 추천
react 프로젝트에서
네비게이션을 login 전과 후에 따라 다르게 표현하고 싶었다.
그러던 중 useEffect 무한루프 문제가 발생했다.
당시 코드는 아래와 같다.
// Bookmark.jsx
function Bookmark() {
const { userC, userCheck } = useUserCheckContext();
useEffect(userCheck, [userC]);
return (
<div className="btn_bookmark_box">
<NavLink className="btn_bookmark home" to="/" activeClassName="active">
HOME
</NavLink>
<NavLink className="btn_bookmark myroom" to={user_id}>
MYROOM
</NavLink>
{userC ? (
<NavLink className="btn_bookmark logout" to="/logout">
Logout
</NavLink>
) : (
<>
<NavLink className="btn_bookmark login" to="/login">
LOGIN
</NavLink>
<NavLink className="btn_bookmark join" to="/signup">
JOIN
</NavLink>
</>
)}
</div>
);
}
useEffect의 두번째 인자를 빈 배열로 지정할 시 새로 랜더링 될 때만 Effect가 발생한다고 하여 변경
그러나 이 경우 로그인 후에 f5를 눌러서 다시 랜더링시켜야 네비게이션에 반영되는 문제가 발생했다. 이때 이상함을 느꼈어야 했는데...
function Bookmark() {
const { userC, userCheck } = useUserCheckContext();
useEffect(userCheck, []);
userC 가 변경될때마다 랜더링이 되어야하는데 토씨하나 다른 게 없어보인다.
여러값이 함께있는 state인 userC 가.. 토씨 하나까지 같다고해도 뭔가가 다를 수 있으니 특정 속성을 지정해줘 봤다.
네비가 달라지는 조건도 변경해주었다.
function Bookmark() {
const { userC, userCheck } = useUserCheckContext();
useEffect(userCheck, [userC.userId]);
return (
<div className="btn_bookmark_box">
<NavLink className="btn_bookmark home" to="/" activeClassName="active">
HOME
</NavLink>
<NavLink className="btn_bookmark myroom" to={user_id}>
MYROOM
</NavLink>
{userC.userId ? (
<NavLink className="btn_bookmark logout" to="/logout">
Logout
</NavLink>
) : (
<>
<NavLink className="btn_bookmark login" to="/login">
LOGIN
</NavLink>
<NavLink className="btn_bookmark join" to="/signup">
JOIN
</NavLink>
</>
)}
</div>
);
}
다행히 무한루프는 멈추었다!
하지만 F5를 누르지 않으면 반영되지 않는 문제가 재발했다... 어째서지?
userCheck state인 userC 의 값이 콘솔에 찍어봤을 때 변경되지 않는 것을 확인했다.
리랜더링을 시켜야 함수가 실행되고 제대로 작동하는 현 상황
로그인으로 인해 새로 랜더링
-> userCheck 함수로 인해 userC의 초기값 셋팅
-> userC는.. 아무 변화가 없는 게 당연함 !
react는 잘못이 없었다.
아무 일도 없는데 왜 변하라고 userC를 닦달했을까?
다시 생각해보았다.
어? 로그인하면 로그인페이지에서 다시 홈으로 돌아오며 랜더링이 되는데 그 전에 처리하면 되는 거 아닌가? 왜 여기서 하고 있지?
로그인을 담당하는 함수 컴포넌트에 가서 랜더링 되기 전 userCheck() 함수를 실행시켜봤다.
// Login.jsx
function Login({ goBackHome }) {
const navigate = useNavigate();
const { user, onChangeHandler } = useUserContext();
// 테스트중입니다
const { userCheck } = useUserCheckContext();
const onLoginEventHandler = async () => {
const res = await LoginFetch(user);
if (res.status === 401) {
window.alert("아이디와 비밀번호를 확인해주세요");
return;
}
window.alert("로그인성공");
// 테스트중입니다
// 로그아웃일때도 해줘야하나
userCheck();
navigate(`/`);
};
이전에 만지던 랜더링 담당 컴포넌트도 단순히 상태만 불러오는 것으로 수정해줬다.
function Bookmark() {
const { userC } = useUserCheckContext();
드디어 로그인 여부에 따라 네비게이션이 변경 되는 것을 확인했다.
나는 이제 잘 것이다.
useCallback을 사용하면 된다는 제보를 들었는데 한번 시도해봐야겠다