개발자
안녕하세요. 현재 wojtekmaj / react-pdf 라이브러리를 사용해서 pdf 관련 개발을 하고 있습니다. + 버튼을 누르면 scale이 올라가고 - 버튼을 누르면 scale이 축소해서 pdf Page의 크기가 변하는데요. 여기서 발생하는 깜빡거림 (?) 을 없애고 싶습니다. 다른 분이 올려주신 질문글 (https://github.com/wojtekmaj/react-pdf/issues/875) 을 보고 페이지가 1개일때에는 해결이 되었는데. 제가 하고싶은 것은 페이지가 1개일 경우가 아닌 모든 페이지를 보여주고, 확대 축소가 발생했을 경우 깜빡거림이 일어나지 않도록 하고 싶습니다. 현재 제 코드에서는 간단하게 로딩상태 일 때 <></> Fragment만 추가해주어도 다시 깜빡거림이 발생하는데요.. 원인을 찾지 못하겠습니다... ( 현재 코드에서 Fragment만 제거하여도 깜빡거림은 사라집니다. ) 아래는 제 코드입니다. 관련하여 도움을 주실분 있으실까요,,?
1import { useEffect, useLayoutEffect, useState } from "react";
2import { pdfjs, Document, Page } from "react-pdf";
3import styled from "styled-components";
4
5pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
6
7const url = "pdf 주소"
8
9const Test = () => {
10 const [numPages, setNumPages] = useState(null);
11 const [scale, setScale] = useState<any>(1);
12 const [renderedScale, setRenderedScale] = useState<any>(null);
13
14 function onDocumentLoadSuccess({ numPages } : any) {
15 setNumPages(numPages);
16 }
17
18 function changeScale(offset : any) {
19 setScale((prevScale : any) => prevScale + offset);
20 }
21
22 function decreaseScale() {
23 changeScale(-0.1);
24 }
25
26 function increaseScale() {
27 changeScale(0.1);
28 }
29
30 const isLoading = renderedScale !== scale;
31
32 return (
33 <Wrapper>
34 <div className="App">
35 <div>
36 <p>Scale {scale}</p>
37
38 <button type="button" disabled={scale <= 0.5} onClick={decreaseScale}>
39 -
40 </button>
41
42 <input
43 type="range"
44 min="0.5"
45 max="2"
46 value={scale}
47 onChange={(event) => setScale(Number(event.target.value))}
48 step="0.1"
49 />
50
51 <button type="button" disabled={scale >= 2} onClick={increaseScale}>
52 +
53 </button>
54 </div>
55 <Container>
56 <Document file={url} onLoadSuccess={onDocumentLoadSuccess}>
57
58 {isLoading ? (
59 <>
60 <Page
61 key={"@" + renderedScale}
62 className="prevPage"
63 pageNumber={1}
64 scale={renderedScale}
65 />
66 </>
67 ) : null}
68
69 <Page
70 key={ "@" + scale}
71 pageNumber={1}
72 onRenderSuccess={() => {
73 setRenderedScale(scale);
74 }}
75 scale={scale}
76 />
77
78 </Document>
79 </Container>
80
81 </div>
82 </Wrapper>
83 );
84};
85
86
87
88
89
90
91
92
93export default Test;
94
95const Wrapper = styled.div`
96 background-color: rgba(0, 0, 0, 0.5);
97 width: 100%;
98 height: 100vh;
99 .App {
100 }
101
102 button {
103 padding: 20px;
104 background-color: blue;
105 }
106
107 canvas {
108 margin: 0 auto;
109 }
110`
111
112const Container = styled.div`
113`
답변 1
안녕하세요! 깜빡거림 문제를 해결해 드리겠습니다. ' react-pdf '의 ' Page ' 컴포넌트가 새로 렌더링 될 때마다 문제가 발생하므로, 이를 방지하기 위해 각 페이지를 캐싱해 두고 확대/축소를 수행하려고 합니다. 이를 위해 ' useRef ' 훅을 사용하여 각 페이지를 DOM에 저장하고, ' useEffect ' 훅을 사용하여 ' scale '이 변경되었을 때 페이지의 스타일을 업데이트하겠습니다. 다음은 수정된 코드입니다 이제 모든 페이지가 한 번만 렌더링되어 캐싱되고, 확대/축소 작업이 수행될 때 DOM 요소의 스타일만 업데이트하므로 깜빡거림이 발생하지 않아야 합니다. 이를 통해 깜빡거림 문제를 해결할 수 있습니다. 코드에 다음과 같은 변경 사항을 적용했습니다: 1. ' useRef '를 사용하여 ' pagesRef '를 생성하고, 이를 통해 각 페이지의 DOM 요소에 대한 참조를 저장합니다. 2. ' Page ' 컴포넌트에 ' inputRef ' prop을 추가하여 각 페이지의 DOM 요소에 대한 참조를 ' pagesRef '에 저장합니다. 이렇게 하면 렌더링된 페이지를 참조할 수 있게 됩니다. 3. ' useEffect '를 사용하여 ' scale '이 변경되었을 때 각 페이지의 스타일을 업데이트합니다. 이렇게 하면 확대/축소 작업을 수행할 때 새로운 렌더링이 발생하지 않고, DOM 요소의 스타일만 업데이트됩니다. 이 수정을 적용한 결과, 모든 페이지가 한 번만 렌더링되어 캐싱되고, 확대/축소 작업이 수행될 때 깜빡거림이 발생하지 않게 되었습니다. 이로써 문제를 해결할 수 있었습니다. 만약 추가적인 도움이 필요하시거나 다른 질문이 있으시면 언제든지 알려주세요!
1import { useEffect, useRef, useState } from "react";
2import { pdfjs, Document, Page } from "react-pdf";
3import styled from "styled-components";
4
5pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
6
7const url = "pdf 주소";
8
9const Test = () => {
10 const [numPages, setNumPages] = useState(null);
11 const [scale, setScale] = useState<any>(1);
12
13 const pagesRef = useRef<any[]>([]);
14
15 function onDocumentLoadSuccess({ numPages }: any) {
16 setNumPages(numPages);
17 }
18
19 function changeScale(offset: any) {
20 setScale((prevScale: any) => prevScale + offset);
21 }
22
23 function decreaseScale() {
24 changeScale(-0.1);
25 }
26
27 function increaseScale() {
28 changeScale(0.1);
29 }
30
31 useEffect(() => {
32 pagesRef.current.forEach((page: any) => {
33 if (page) {
34 page.style.transform = `scale(${scale})`;
35 }
36 });
37 }, [scale]);
38
39 return (
40 <Wrapper>
41 <div className="App">
42 <div>
43 <p>Scale {scale}</p>
44
45 <button
46 type="button"
47 disabled={scale <= 0.5}
48 onClick={decreaseScale}
49 >
50 -
51 </button>
52
53 <input
54 type="range"
55 min="0.5"
56 max="2"
57 value={scale}
58 onChange={(event) => setScale(Number(event.target.value))}
59 step="0.1"
60 />
61
62 <button
63 type="button"
64 disabled={scale >= 2}
65 onClick={increaseScale}
66 >
67 +
68 </button>
69 </div>
70 <Container>
71 <Document file={url} onLoadSuccess={onDocumentLoadSuccess}>
72 {Array.from(new Array(numPages), (_, index) => (
73 <Page
74 key={`page_${index + 1}`}
75 inputRef={(page: any) => {
76 pagesRef.current[index] = page;
77 }}
78 pageNumber={index + 1}
79 scale={1}
80 />
81 ))}
82 </Document>
83 </Container>
84 </div>
85 </Wrapper>
86 );
87};
88
89export default Test;
90
91const Wrapper = styled.div`
92 background-color: rgba(0, 0, 0, 0.5);
93 width: 100%;
94 height: 100vh;
95 .App {
96 }
97
98 button {
99 padding: 20px;
100 background-color: blue;
101 }
102
103 canvas {
104 margin: 0 auto;
105 }
106`;
107
108const Container = styled.div``;
커리어리 AI 봇의 답변을 평가해 주세요!
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
지금 가입하면 모든 질문의 답변을 볼 수 있어요!