react 의 dom element 에 접근해서 d3 로 전달하려면 useRef 라는 hook 이 필요하다.
select 를 import 해서 svg 를 사용할 수 있게 한다.
data 를 import 해준다.
이렇게까지 해주면 d3 로 뭔가를 그릴 준비가 된 것이다.
d3 에게 모든 circle 을 select 해줘. 그런데 그 circle 에 data 를 동기화해줘. 라고 말한다.
d3 에게 svg 에 어떤 element 를 enter 해야하는지, update 해야하는지, remove 해야하는지 말해줘야 한다.
join 메서드에 콜백함수로 enter, update, exit 을 적어준다. 확인해보면 이렇게 circle 이 data 배열의 길이만큼 생성된 것을 알 수 있다.
.attr("class", "new") 이런 식으로 적어주면 svg 요소에 class 명을 넣어줄 수 있다.
update 와 exit 을 확인하기 위해서는 data 가 변해야 한다. cra 는 변화가 모두 일어나고 난 후에야 렌더링되기 때문에 지금은 확인할 수 없다.
button 을 하나 만들고 button 을 클릭했을 때 data 를 업데이트 시켜보자. (svg 의 update 가 작동하는지 확인할 수 있다.) data 를 useState 를 사용해서 state 에 저장하고 업데이트 할 것이다.
button 을 누르고 개발자도구에서 확인하면 class 명이 new 에서 update 로 바뀐 것을 확인할 수 있다. svg 의 update 가 작동하는 것!
filter button 을 생성해서 data 값이 35 이하인 svg 만 보여줄 수 있다. 원래 5개이던 svg 의 개수가 조건에 따라 3개만 보여진다.
위 작업이 이루어지는 과정은 이렇다. 버튼이 클릭되면 data 가 변하므로 useEffect 가 작동한다. d3 가 circle 인 svg 를 모두 가져온다. 3개는 update 하고 2개는 remove 한다.
.join 으로 할 수 있는 놀라운 일은 더 있다. 아래와 같이 적어주면 동그라미를 만들 수 있다. r 은 원의 반경, cx 는 가로축, cy 는 세로축을 의미한다.
그런데 update 버튼을 클릭하면 class 명만 update 로 바뀌고 r 이나 cx, cy 가 바뀌지는 않는다. enter 에 적은 attr 부분을 update 에도 똑같이 적어줘야 update 버튼을 클릭했을 때 실제로 업데이트가 된다.
그런데 같은 내용을 enter 와 update 에 반복해서 적어주는 것은 바보같다!! 반복을 피하기 위해서 반복되는 내용을 join 메서드 뒤에 적어주면 enter 와 update 에 둘 다 적용된다. 수정된 코드는 아래와 같다.
그리고 remove 메서드는 d3 의 default 메서드이기 때문에 적어주지 않아도 된다. filter 를 하면 지워야 할 svg element 를 저절로 지워주기 때문에 remove 를 적어주지 않아도 되는 것이다. 수정된 코드는 아래와 같다.
또, 필요없는 속성들을 지우고 나면 다음과 같은 코드가 된다. 코드가 깔끔해졌다. join 메서드는 join 안에 있는 svg element 를 생성하고(enter) update 하며 remove 한다.
여기까지가 d3 가 어떻게 svg element 를 생성하고 업데이트하고 삭제하는지에 대한 기본적인 flow 이다.