회사에서 jquery 를 사용한 프로젝트를 React 로 포팅하는 도중
beforeprint, afterprint 이벤트를 처리하는 함수를 마주했습니다.
window.print() 를 호출하기 전, 화면의 특정 요소를 숨기고(.hide())
사용자가 print 화면을 닫게 되면 다시 화면의 특정 요소를 보여주는(.show()) 로직이었습니다.
printing이라는 상태를 통해 요소를 숨기고 보여주는 코드를 아래와 같이 작성했습니다.
import { useState, useEffect } from "react";
const printingExample = () => {
const [isPrinting, setIsPrinting] = useState(false);
const handleBeforeprint = () => setIsPrinting(true);
const handleAfterprint = () => setIsPrinting(false);
useEffect(() => {
window.addEventListener("beforeprint", handleBeforeprint);
window.addEventListener("afterprint", handleAfterprint);
return () => {
window.removeEventListener("beforeprint", handleBeforeprint);
window.removeEventListener("afterprint", handleAfterprint);
};
});
return isPrinting;
};
export default printingExample;
예상한 것과 달리 로직은 제대로 작동하지 않았습니다.
React 에서 업데이트는 일반적으로 비동기적으로 처리되며 다음 렌더 시에 반영이 됩니다.
React 18부터 flushSync API 가 추가 되었습니다. 비동기적으로 처리하는 작업을 강제로 동기로 처리하도록 하는 것인데
React-dom 가이드북에 flushSync API에는 마침 beforeprint 를 처리하는 코드가 샘플로 작성되어 있었습니다.
그래서 간단히 아래와 같이 코드를 변경해서 훅으로 사용할 수 있었습니다.(handleBeforeprint 를 확인하세요)
import { useState, useEffect } from "react";
const useDetectPrint = () => {
const [isPrinting, setIsPrinting] = useState(false);
const handleBeforeprint = flushSync(() => setIsPrinting(true));
const handleAfterprint = () => setIsPrinting(false);
useEffect(() => {
window.addEventListener("beforeprint", handleBeforeprint);
window.addEventListener("afterprint", handleAfterprint);
return () => {
window.removeEventListener("beforeprint", handleBeforeprint);
window.removeEventListener("afterprint", handleAfterprint);
};
});
return isPrinting;
};
export default useDetectPrint;
'Front-End > React' 카테고리의 다른 글
React Portal (0) | 2023.10.06 |
---|---|
Next Module Alias @ (0) | 2023.09.22 |
React snippets (0) | 2023.09.20 |
TypeError Cannot read property 'setState' of undefined (0) | 2022.02.10 |
댓글