react-chartjs-2 Cannot delete property ‘push’ of [object Array] 에러 해결

Jin·2023년 9월 13일
0

chartjs를 사용하다보면 Cannot delete property ‘push’ of [object Array] 에러를 접할 수 있습니다.
저의 경우에는 차트의 데이터에 들어가는 배열을 여러 군데에서 동시에 사용하면서 여러 군데에서 같은 차트를 렌더하고 난 이후에, 차트를 업데이트시키려고 했을 때 발생했습니다.

이 에러 관련하여 발견한 상황은 다음과 같습니다.

  • chartjs에 data를 넘길때 변경사항 감지를 위해 배열에 _chartJs 프로퍼티를 assign함
  • chartjs에서 차트가 제거 or 데이터 변경될 때 data 배열의 주소가 바뀌었으면 unlistenArrayEvents 호출
  • 해당 함수에서는 _chartJs 프로퍼티가 있는 경우 등록했던 listener를 제거함
  • 그런데 차트 항목을 바꾸거나 data 배열의 길이가 늘어난다거나 하는 등의 상황이 발생했을 때 아래 오류 발생
    Cannot delete property ‘push’ of [object Array]
  • _chartJs 프로퍼티는 있으면서 기존에 unlistenArrayEvents 함수가 호출(=push 제거)되었던 배열에 이를 다시 호출하면 push가 이미 지워진 상태이므로 다시 지울 수 없을 것 같음

더 자세히 알기 위해서는 라이브러리 내부 코드를 뜯어봐야 했고 확신할 수는 없지만 다음과 같은 동작을 하는 것으로 추측하였습니다.

  • 라이브러리 내부에서 Array를 in-place하게 건드는 로직이 있음
  • Array 변경 감지시 캔버스 반영을 위해 listenArrayEvents 함수를 호출하여 array 함수를 listener를 호출하도록 rewrite
  • unlistenArrayEvents 함수가 호출되면 listener를 붙였던 array의 property(push 등)를 delete함
    • _chartjs 프로퍼티가 있는(listenArrayEvent가 돌았던) 배열 한정
  • unlistenArrayEvents가 2번 이상 돌면 _chartjs 프로퍼티는 살아있지만 push 속성이 앞선 호출에서 사라진 이후라 해당 오류가 발생

이를 해결하기 위해서는 여러 군데에서 렌더시, 차트가 들어갈 데이터 배열이 공유되지 않도록 chartData에 들어가는 배열을 매번 새 배열을 생성하여 주입하였습니다.


  const chartData: ChartData = {
    ...
    datasets: [
      {
        data: [...data], // 이전에는 data 자체를 주입했다면 이제는 새로운 배열로 주입
        ...
      },
    ],
  };
profile
배워서 공유하기

0개의 댓글

Powered by GraphCDN, the GraphQL CDN