“Cannot read properties of undefined (reading ‘notifyPlugins’)” – chart.js

huangapple go评论70阅读模式
英文:

Cannot read properties of undefined (reading 'notifyPlugins') - chart.js

问题

我明白你的要求,以下是翻译好的部分:

问题描述:
当从图表页面导航离开时,为什么我的图表会尝试读取 notifyPlugins('beforeDestroy')

我有一个插件文件、一个 Svelte 动作以及一个主文件 [ChartMetrics.svelte](其中使用了该动作)。当前的行为是,在主页面中图表完全正常加载,但当导航到另一个页面时,我遇到了 notifyPlugins 错误。我已经添加了项目中最相关的代码,因为整个代码库相当大,无法将其添加到 CodeSandbox。是否有人在使用 chart.js 时曾遇到过 notifyPlugins 错误?如果你需要看更多代码,请告诉我。

控制台错误:

chart.js:6171 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'notifyPlugins')
    at destroy (chart.js:6171:1)
    at Object.destroy [as d] (ChartMetrics.svelte:454:1)
    at Object.destroy [as d] (Div.svelte:127:1)
    at destroy_component (index.mjs:1974:1)
    at Object.destroy [as d] (ChartMetrics.svelte:127:1)
    at Object.destroy [as d] (ChartMetrics.svelte:535:1)
    at destroy_component (index.mjs:1974:1)
    at Object.destroy [as d] (EffectiveMaterialAssetsMetricsContainer.svelte:71:1)
    at Object.destroy [as d] (MetricWrapper.svelte:133:1)
    at Object.destroy [as d] (MetricWrapper.svelte:308:1)

chart.js (第6171行):

destroy() {
   this.notifyPlugins('beforeDestroy');
   ....
}

ChartMetrics (第454行):

d: function destroy(detaching) {
    if (detaching) detach_dev(div0);
    if_blocks[current_block_type_index].d();
    destroy_component(tooltipinfo);
    destroy_component(anchor);
    if (detaching) detach_dev(t3);
    if (detaching) detach_dev(div1);
    mounted = false;
    dispose();
}

ChartMetrics 第454行(图像):
“Cannot read properties of undefined (reading ‘notifyPlugins’)” – chart.js

plugins.ts:

export function textPlugin(value: number, theme: Theme) {
  return {
    id: "chartTextPlugin",
    // 在图表中间写入文本的插件
    beforeDraw: function (chart: ChartType) {
      // 在 chart.js 图表上绘制一些文本的插件
    },
  }
}

export function curvePlugin() {
  // 曲线化环形图的边缘
  return {
    id: "chartCurvePlugin",
    afterUpdate: function (chart: ChartType) {
      // 一些代码来曲线化 chart.js 图表的边缘
    },
    afterDraw: function (chart: ChartType) {
      // 一些代码来执行与上面相同的操作
    },
  }
}

add-chart.ts(Svelte 动作):

export const addChart = (node: HTMLElement, params: ChartProps): ChartGauge => {
  const text = textPlugin(params.value, params.theme);
  const curve = curvePlugin();
  const backgroundColor = mapTypeToColor(params.theme);

  return new Chart(node, {
    type: "doughnut",
    data: {
      datasets: [
        {
          //label: params.caption,
          data: [params.value, 100 - params.value],
          backgroundColor: backgroundColor,
          borderColor: ["rgba(255, 255, 255 ,1)"],
          borderWidth: 0,
        },
      ],
    },
    options: {
      rotation: -90,
      cutout: "85%",
      circumference: 180,
      radius: "85%",
      responsive: true,
      maintainAspectRatio: true,
      aspectRatio: 3,
    },
    plugins: [text, curve],
  });
}

ChartMetrics.svelte:

{#if value >= 0 && value <= 100}
  <CardDiv p={4} pl={4} pr={4}>
    <div class="metrics-header">
      <h3>
        Controls -
        {#if titleUrl}
          <Anchor href={titleUrl} size={14}>{title}</Anchor>
        {:else}
          <span>{title}</span>
        {/if}
        <TooltipInfo content={tooltipContent} id="info" width="small" />
      </h3>
      <Anchor href={assuranceUrl} size={14}>View Assurance</Anchor>
    </div>
    <div class="chart">
      <canvas
        id="chart"
        data-test-id="chart"
        use:addChart={{ value, theme }}
        style="height:100%;width:100%;"
      />
    </div>
  </CardDiv>
{:else}
  <MetricsError message="Chart Metrics Widget Error: Invalid value." />
{/if}

希望这些翻译对你有所帮助。如果有其他问题,请随时提出。

英文:

Why is my chart attempting to read notifyPlugins('beforeDestroy') when navigating away from the page of the chart?

I have a plugins file, a svelte action and a main file [ChartMetrics.svelte] (where the action is used). The current behaviour is that the chart loads completely fine in the main page, but when navigating to another page I am met with the notifyPlugins error. I have added the most relevant code from my project, as the entire codebase is quite large so would be unable to add it to a codesandbox. Has anyone recieved this error with notifyPlugins before when working with chart.js? If there is any more code you need to see let me know.

console error:

chart.js:6171 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading &#39;notifyPlugins&#39;)
    at destroy (chart.js:6171:1)
    at Object.destroy [as d] (ChartMetrics.svelte:454:1)
    at Object.destroy [as d] (Div.svelte:127:1)
    at destroy_component (index.mjs:1974:1)
    at Object.destroy [as d] (ChartMetrics.svelte:127:1)
    at Object.destroy [as d] (ChartMetrics.svelte:535:1)
    at destroy_component (index.mjs:1974:1)
    at Object.destroy [as d] (EffectiveMaterialAssetsMetricsContainer.svelte:71:1)
    at Object.destroy [as d] (MetricWrapper.svelte:133:1)
    at Object.destroy [as d] (MetricWrapper.svelte:308:1)

chart.js (line 6171):

destroy() {
   this.notifyPlugins(&#39;beforeDestroy&#39;);
   ....
}

ChartMetrics (line 454):

		d: function destroy(detaching) {
			if (detaching) detach_dev(div0);
			if_blocks[current_block_type_index].d();
			destroy_component(tooltipinfo);
			destroy_component(anchor);
			if (detaching) detach_dev(t3);
			if (detaching) detach_dev(div1);
			mounted = false;
			dispose();
		}

ChartMetrics line 454 (image):
“Cannot read properties of undefined (reading ‘notifyPlugins’)” – chart.js

plugins.ts:

export function textPlugin(value: number, theme: Theme) {
  return {
    id: &quot;chartTextPlugin&quot;,
    // Plugin for writing text in middle of chart
    beforeDraw: function (chart: ChartType) {
      plugin that draws some text on a chart.js chart
    },
  }
}

export function curvePlugin() {
  // Curve edges of donut
  return {
    id: &quot;chartCurvePlugin&quot;,
    afterUpdate: function (chart: ChartType) {
      // some code to curve the edges of the chart.js chart
      }
    },
    afterDraw: function (chart: ChartType) {
      // some more code to do same as above
    },
  }
}

add-chart.ts (svelte action)

export const addChart = (node: HTMLElement, params: ChartProps): ChartGauge =&gt; {
  const text = textPlugin(params.value, params.theme)
  const curve = curvePlugin()
  const backgroundColor = mapTypeToColor(params.theme)

  return new Chart(node, {
    type: &quot;doughnut&quot;,
    data: {
      datasets: [
        {
          //label: params.caption,
          data: [params.value, 100 - params.value],
          backgroundColor: backgroundColor,
          borderColor: [&quot;rgba(255, 255, 255 ,1)&quot;],
          borderWidth: 0,
        },
      ],
    },
    options: {
      rotation: -90,
      cutout: &quot;85%&quot;,
      circumference: 180,
      radius: &quot;85%&quot;,
      responsive: true,
      maintainAspectRatio: true,
      aspectRatio: 3,
    },
    plugins: [text, curve],
  })
}

ChartMetrics.svelte

{#if value &gt;= 0 &amp;&amp; value &lt;= 100}
  &lt;CardDiv p={4} pl={4} pr={4}&gt;
    &lt;div class=&quot;metrics-header&quot;&gt;
      &lt;h3&gt;
        Controls -
        {#if titleUrl}
          &lt;Anchor href={titleUrl} size={14}&gt;{title}&lt;/Anchor&gt;
        {:else}
          &lt;span&gt;{title}&lt;/span&gt;
        {/if}
        &lt;TooltipInfo content={tooltipContent} id=&quot;info&quot; width=&quot;small&quot; /&gt;
      &lt;/h3&gt;
      &lt;Anchor href={assuranceUrl} size={14}&gt;View Assurance&lt;/Anchor&gt;
    &lt;/div&gt;
    &lt;div class=&quot;chart&quot;&gt;
      &lt;canvas
        id=&quot;chart&quot;
        data-test-id=&quot;chart&quot;
        use:addChart={{ value, theme }}
        style=&quot;height:100%;width:100%;&quot;
      /&gt;
    &lt;/div&gt;
  &lt;/CardDiv&gt;
{:else}
  &lt;MetricsError message=&quot;Chart Metrics Widget Error: Invalid value.&quot; /&gt;
{/if}

答案1

得分: 0

你可以尝试这个解决方案的补丁:在 add-chart.ts 中,替换

return new Chart(node, {
..... 
});

使用

const chart = new Chart(node, {
    ......
});
chart.destroy = chart.destroy.bind(chart);
return chart;

更符合 Svelte 风格的方式可能是

return {
   ...chart,
   destroy(){
      chart.destroy();
   }
}

但这可能需要一些 TypeScript 的技巧来通过类型检查。

英文:

You could try this patch of a solution: in add-chart.ts instead of

return new Chart(node, {
.....
});

use

const chart = new Chart(node, {
    .....
});
chart.destroy = chart.destroy.bind(chart);
return chart; 

A more svelte-idiomatic way might be

return {
   ...chart,
   destroy(){
      chart.destroy();
   }
}

but that would probably need some typescript acrobatics to pass type-checking.

huangapple
  • 本文由 发表于 2023年5月26日 14:23:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76338118.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定