개발자

React state 변경시 PDF 깜빡거림 질문입니다!

2023년 04월 17일조회 256

안녕하세요. 현재 wojtekmaj / react-pdf 라이브러리를 사용해서 pdf 관련 개발을 하고 있습니다. + 버튼을 누르면 scale이 올라가고 - 버튼을 누르면 scale이 축소해서 pdf Page의 크기가 변하는데요. 여기서 발생하는 깜빡거림 (?) 을 없애고 싶습니다. 다른 분이 올려주신 질문글 (https://github.com/wojtekmaj/react-pdf/issues/875) 을 보고 페이지가 1개일때에는 해결이 되었는데. 제가 하고싶은 것은 페이지가 1개일 경우가 아닌 모든 페이지를 보여주고, 확대 축소가 발생했을 경우 깜빡거림이 일어나지 않도록 하고 싶습니다. 현재 제 코드에서는 간단하게 로딩상태 일 때 <></> Fragment만 추가해주어도 다시 깜빡거림이 발생하는데요.. 원인을 찾지 못하겠습니다... ( 현재 코드에서 Fragment만 제거하여도 깜빡거림은 사라집니다. ) 아래는 제 코드입니다. 관련하여 도움을 주실분 있으실까요,,?

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.

답변 1

커리어리 AI 봇님의 프로필 사진

안녕하세요! 깜빡거림 문제를 해결해 드리겠습니다. ' react-pdf '의 ' Page ' 컴포넌트가 새로 렌더링 될 때마다 문제가 발생하므로, 이를 방지하기 위해 각 페이지를 캐싱해 두고 확대/축소를 수행하려고 합니다. 이를 위해 ' useRef ' 훅을 사용하여 각 페이지를 DOM에 저장하고, ' useEffect ' 훅을 사용하여 ' scale '이 변경되었을 때 페이지의 스타일을 업데이트하겠습니다. 다음은 수정된 코드입니다 이제 모든 페이지가 한 번만 렌더링되어 캐싱되고, 확대/축소 작업이 수행될 때 DOM 요소의 스타일만 업데이트하므로 깜빡거림이 발생하지 않아야 합니다. 이를 통해 깜빡거림 문제를 해결할 수 있습니다. 코드에 다음과 같은 변경 사항을 적용했습니다: 1. ' useRef '를 사용하여 ' pagesRef '를 생성하고, 이를 통해 각 페이지의 DOM 요소에 대한 참조를 저장합니다. 2. ' Page ' 컴포넌트에 ' inputRef ' prop을 추가하여 각 페이지의 DOM 요소에 대한 참조를 ' pagesRef '에 저장합니다. 이렇게 하면 렌더링된 페이지를 참조할 수 있게 됩니다. 3. ' useEffect '를 사용하여 ' scale '이 변경되었을 때 각 페이지의 스타일을 업데이트합니다. 이렇게 하면 확대/축소 작업을 수행할 때 새로운 렌더링이 발생하지 않고, DOM 요소의 스타일만 업데이트됩니다. 이 수정을 적용한 결과, 모든 페이지가 한 번만 렌더링되어 캐싱되고, 확대/축소 작업이 수행될 때 깜빡거림이 발생하지 않게 되었습니다. 이로써 문제를 해결할 수 있었습니다. 만약 추가적인 도움이 필요하시거나 다른 질문이 있으시면 언제든지 알려주세요!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { useEffect, useRef, useState } from "react";
import { pdfjs, Document, Page } from "react-pdf";
import styled from "styled-components";

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;

const url = "pdf 주소";

const Test = () => {
  const [numPages, setNumPages] = useState(null);
  const [scale, setScale] = useState<any>(1);

  const pagesRef = useRef<any[]>([]);

  function onDocumentLoadSuccess({ numPages }: any) {
    setNumPages(numPages);
  }

  function changeScale(offset: any) {
    setScale((prevScale: any) => prevScale + offset);
  }

  function decreaseScale() {
    changeScale(-0.1);
  }

  function increaseScale() {
    changeScale(0.1);
  }

  useEffect(() => {
    pagesRef.current.forEach((page: any) => {
      if (page) {
        page.style.transform = `scale(${scale})`;
      }
    });
  }, [scale]);

  return (
    <Wrapper>
      <div className="App">
        <div>
          <p>Scale {scale}</p>

          <button
            type="button"
            disabled={scale <= 0.5}
            onClick={decreaseScale}
          >
            -
          </button>

          <input
            type="range"
            min="0.5"
            max="2"
            value={scale}
            onChange={(event) => setScale(Number(event.target.value))}
            step="0.1"
          />

          <button
            type="button"
            disabled={scale >= 2}
            onClick={increaseScale}
          >
            +
          </button>
        </div>
        <Container>
          <Document file={url} onLoadSuccess={onDocumentLoadSuccess}>
            {Array.from(new Array(numPages), (_, index) => (
              <Page
                key={`page_${index + 1}`}
                inputRef={(page: any) => {
                  pagesRef.current[index] = page;
                }}
                pageNumber={index + 1}
                scale={1}
              />
            ))}
          </Document>
        </Container>
      </div>
    </Wrapper>
  );
};

export default Test;

const Wrapper = styled.div`
  background-color: rgba(0, 0, 0, 0.5);
  width: 100%;
  height: 100vh;
  .App {
  }

  button {
    padding: 20px;
    background-color: blue;
  }

  canvas {
    margin: 0 auto;
  }
`;

const Container = styled.div``;

커리어리 AI 봇의 답변을 평가해 주세요!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!