I am trying to write a function drawChart
that is called each time my variable stats
changes to update my current chart.
I am able to draw my initial chart when using onMount
, but when I fetch new stats, the chart does not update.
I can't figure out how to do this in Sapper because my function also relies on the canvas
element to use for my chart's context.
I tried writing a reactive statement such as $: drawChart(chartContext, stats)
, but chartContext
is undefined.
My code:
<script>
import { onMount } from 'svelte';
import Chart from 'chart.js';
export let stats;
let chartContext;
let chartCanvas;
let chart;
onMount(() => {
chartContext = chartCanvas.getContext('2d');
drawChart(chartContext, stats);
})
const drawChart = (chartContext, stats) => {
const s = fetchStats(stats);
chart = new Chart(chartContext, {
type: 'bar',
data: {
labels: s.seasons,
datasets: [{
label: s.stat1.label,
data: s.stat1.data,
backgroundColor: 'whitesmoke',
borderColor: 'black',
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
maintainAspectRatio: false,
responsive: true
}
});
}
// I want this to be called each time stats is updated, but it does not work as chartContext is undefined here
$: drawChart(chartContext, stats);
</script>
<canvas id="chart" width="200" height="200" aria-label="chart" role="figure" bind:this={chartCanvas}></canvas>
Is there a way to solve this issue? Any help is greatly appreciated :)
Yes, it is expected that you get a run of the reactive block when chartContext
is still undefined. It happens before onMount
. Svelte simply runs the reactive block anytime any of the depended variable changes, and this includes their initial values. Svelte doesn't wait for the component to be mounted in the DOM before running reactive blocks or anything like that.
So you simply need to account for this special case in your code:
$: if (chartContext) drawChart(chartContext, stats)
Here. All set. (You may also want to ensure that stats
is set in the same fashion, to make your component more resilient to what its consumers might possibly send to it.)