Error Handling

D3 요소가 연속 렌더링 되는 경우

KANG_G1 2023. 10. 5. 10:57

Next.js에서 D3 라이브러리로 도형을 그려내던 중 이상한 점을 발견했는데요.

제가 작성한 요소는 사각형, 원, 선,텍스트 4개였는데 이보다 많은 요소가 화면에 출력되고 있었습니다.

문제의 코드

import React, { useEffect } from "react";
import * as d3 from "d3";

const Lesson02 = () => {
  useEffect(() => {
    const canvas = d3.select(".canvas");

    const svg = canvas.append("svg").attr("width", 600).attr("height", 600);
    const group = svg.append("g");

    group
      .append("rect")
      .attr("width", 200)
      .attr("height", 100)
      .attr("fill", "blue")
      .attr("x", 20)
      .attr("y", 20);

    group.append("circle");

    group.append("line");

    group
      .append("text")
      .attr("x", 20)
      .attr("y", 200)
      .attr("fill", "grey")
      .text("D3 practice");
  }, []);

  return <div className="canvas"></div>;
};

export default Lesson02;

코드에서 볼 수 있다시피 rect, circle, line, text 4개를 작성했는데 여러 개가 보여진다는 점은

useEffect 내부에 이유가 있다는 게 확실했거든요.

 

Lesson02 컴포넌트 마운팅 시 svg 요소들이 DOM에 이미 존재하니 canvas className을 지닌 div에

추가로 생성되지 않아야 하는데, 여기서 해결 실마리에 대한 감이 왔습니다.

 

useEffect 내부에서 사용되는 D3의 append 메서드가 이유였어요.

기존 요소에 새로운 요소를 추가하는 역할을 수행하는데

useEffect가 실행될 때마다 새로운 SVG와 .canvas div에 추가되어

원치 않은 다량의 요소들이 보여지는 것이었습니다.

 

해결

if문 분기처리로 기존 canvas에 존재하는 svg 요소를 삭제해주면 문제가 해결됩니다!

import React, { useEffect } from "react";
import * as d3 from "d3";

const Lesson02 = () => {
  useEffect(() => {
    const canvas = d3.select(".canvas");

    // 기존 svg 삭제
    if (canvas.select("svg")) {
      canvas.select("svg").remove();
    }

    const svg = canvas.append("svg").attr("width", 600).attr("height", 600);
    
    const group = svg.append("g");

    group
      .append("rect")
      .attr("width", 200)
      .attr("height", 100)
      .attr("fill", "blue")
      .attr("x", 20)
      .attr("y", 20);

    group.append("circle");
    
    group.append("line");

    group
      .append('text')
      .attr('x',20)
      .attr('y',200)
      .attr('fill','grey')
      .text('D3 practice');
      
}, []);

return <div className="canvas"></div>;
};

export default Lesson02;

 

단순히 Next.js에서만 발생하는 것이 아닌, React와 useEffect 동작 방식에 대한 이해가 필요했고

D3에서 사용되는 메서드의 특징을 몰라 발생했던 에러였습니다.

오랜만에 React의 동작 방식에 대해 살펴볼 수 있어 유익한 오류였어요!