그냥 남의 글 보고 코드 베꼈는데....잘 동작한다...
왜지...?
아무튼 굿 😶
+토글 아니고 모달 창이라고 해야 하는 것 알지만 귀찮아서 코드 수정 안했음
const Toggle = () => {
const [isToggleClicked, setIsToggleClicked] = useState(false);
const inSection = useRef();
const onClick = () => {
setIsToggleClicked((prev) => !prev);
};
useEffect(() => {
const clickOutside = (e) => {
if (
isToggleClicked &&
!inSection.current.contains(e.target)
) {
setIsToggleClicked(false);
}
};
document.addEventListener("mousedown", clickOutside);
return () => {
document.removeEventListener("mousedown", clickOutside);
};
}, [isToggleClicked]);
return (
<StyledDiv ref={inSection} className="toggle-box">
<button className="toggle-button" onClick={onClick}>
<RxHamburgerMenu />
</button>
{isToggleClicked && <ToggleContents />}
</StyledDiv>
);
};
export default Toggle;
toggle box 전체를 ref로 만듦.
isToggleClicked가 true이면서 && inSection.current(=toggle box div)가 e.target(클릭된 부분)을 포함하지 않을시 isToggleClicked를 false로 바꿈 (=토글 닫기)
컴포넌트가 언마운트될 때 이벤트리스너를 삭제하는 코드를 작성했으나 이 컴포넌트는 화면에 항상 있는 애라서 딱히 소용 X...
이 블로그가 정리가 잘 돼있어서 많이 참고했다.
자바스크립트에서 querySelector로 DOM 요소를 직접 선택하는 것처럼, 리액트에서는 DOM 요소 선택시 useRef 라는 React Hook을 사용한다.
📌 useRef로 DOM 요소를 선택할 수 있다.
const inputRef = useRef();
function focus() {
inputRef.current.focus();
console.log(inputRef.current);
}
return (
<div>
<input ref={inputRef} type="text" placeholder="아이디 또는 이메일" />
<button>Login</button>
<br />
<button onClick={focus}>focus</button>
</div>
);
input 태그를 ref로 만들면, inputRef의 current가 input 태그가 된다.
📌 useRef로 관리하는 변수는 값이 변해도 화면에 렌더링되지 않는다.
useEffect안에서의 set state 변경 때문에 무한루프에 빠질 때 효율적으로 해결할 수 있는 방법 중 하나가 된다.