dukDukz
[React] (useRef 활용) 함수를 특정 페이지에서만 동작하지 않게 하기 본문
구현 목표
1) As is
App.js 에서 페이지 이동시마다 loginCheck 함수를 호출시킴
2) To be
"페이지를 찾을 수 없음" - NoMatch.jsx 에서 loginCheck 함수를 제외시키고 싶음.
useRef를 통해 해결
App.jsx
const noMatch = useRef();
useEffect(() => {
if (!noMatch.current) {
loginCheck(token);
} else {
return;
}
}, [token, loginCheck]);
noMatch 값을 props로 NoMatch 컴포넌트에 넘겨준다.
NoMatch.jsx
import React from 'react';
import { useNavigate } from 'react-router-dom';
export default function NoMatch({ noMatch }) {
const navigate = useNavigate();
return (
<div id="no-match" ref={noMatch}>
<h2>페이지를 찾을 수 없습니다.</h2>
<button
className="btn btn-danger"
onClick={() => {
navigate(-1);
}}>
뒤로가기
</button>
</div>
);
}
평소에는 noMatch.current = undefined 가 뜬다.
noMatch.current는 falsy 하므로 if문에 걸려서 loginCheck 가 진행된다. (OK!)
"페이지를 찾을 수 없음"- NoMatch 컴포넌트에 접근하게 되면 noMatch ref를 찾을 수 있다.
이때는 noMatch.current 가 truthy 함.
그래서 else 문으로 빠지게 되어 loginCheck를 진행하지 않는다. (OK!)
useRef로 변경 전에는...
const nomatchtext = document.getElementById('no-match');
if (!nomatchtext) {
loginCheck(token);
} else {
return;
}
이런식으로 id 값을 가져와서 했는데 당연히 이것도 된다.
근데 React에서는 useRef 사용을 권장하니까 바꿨다.
시도 1
1) useState 활용하기 - 실패
App.jsx
const [noMatch, setNoMatch] = useState(false);
useEffect(() => {
if (!noMatch) loginCheck(token);
}, [noMatch, token, loginCheck]);
NoMatch.jsx
export default function NoMatch({ noMatch }) {
useEffect(() => {
setNoMatch(true);
return function cleanup() {
setNoMatch(false);
};
}, []);
return (
<div id="no-match">
<h2>페이지를 찾을 수 없습니다.</h2>
<button
onClick={() => {
setNoMatch(false);
navigate(-1);
}}
>
뒤로가기
</button>
</div>
);
}
처음에는 useEffect에서 상태값을 변경하고 뒤로가기 버튼을 눌렀을 때 다시 초기값으로 변경되게 하려고 했는데 이전 페이지로 돌아가도 계속 상태값이 true로 남아있었다.
useEffect 내부에서 cleanup을 안써줘서 그랬던 것. cleanup 함수를 사용하니 값이 초기값으로 변경되는 것을 확인할 수 있었다.
(메가테라 4주차 - 3강 부분...)
2) 결과 => 실패
state를 NoMatch 컴포넌트에 넘겨주는데 기존 상태값(false)에서 true로 변경되긴 하는데
App.js 의 if 절에 걸려서 변경되기 전 상태 값이 인식되어 loginCheck 함수로 빠짐.
시도 2
1) redux 활용하기 - 실패
state의 문제인가 싶어서 redux 사용으로 변경
App.jsx
const noMatch = useSelector((state) => state.menu.noMatchStatus);
useEffect(() => {
if (!noMatch) {
loginCheck(token);
}
}, [noMatch, token, loginCheck]);
NoMatch.jsx
function NoMatch() {
const navigate = useNavigate();
const dispatch = useDispatch();
useEffect(() => {
dispatch(setNoMatch({ status: true }));
return function cleanup() {
dispatch(setNoMatch({ status: false }));
};
}, []);
return (
<div className="no-match">
<h2>페이지를 찾을 수 없습니다.</h2>
<button
onClick={() => {
dispatch(setNoMatch({ status: false }));
navigate(-1);
}}
>
뒤로가기
</button>
</div>
);
}
2) 결과 => 실패
redux에서 SetNoMatch 함수를 가져와서 상태값을 변경한다.
이것 역시 기존 상태값(false)에서 true로 변경되긴 하는데
App.js 의 if 절에 걸려서 변경되기 전 상태 값이 인식되어 loginCheck 함수로 빠짐.
'웹 개발 > React' 카테고리의 다른 글
[React Router v6] createBrowserRouter 레이아웃 여러개 (0) | 2023.04.06 |
---|---|
[error] @parcel/transformer-js: Browser scripts cannot have imports or exports. (0) | 2023.03.02 |
[React] Router replace to (0) | 2022.12.08 |
Uncaught Error: Invariant failed: You should not use <Switch> outside a <Router> (1) | 2022.10.04 |
[React] Route - Redirect (0) | 2022.10.04 |