I tried to follow both the c3 charts docs here: https://c3js.org/samples/chart_donut.html
And this stack overflow here: C3 chart not rendering in react project
But it is still not rendering nor are my console logs showing which means its not being initiating. What logic am I missing?
// rrd imports
import { useLoaderData, useOutletContext } from "react-router-dom";
import { useState, useEffect } from "react";
// library
import { toast } from "react-toastify";
import c3 from 'c3';
import 'c3/c3.css'; // Import the CSS file for styling
import LoadingSpin from '../assets/loading-spin.svg' // Adjust the path to match your file structure
// components
import AddExpenseForm from "../components/AddExpenseForm";
import BudgetItem from "../components/BudgetItem";
import Table from "../components/Table";
// helpers
import { createExpense, deleteItem } from "../helpers";
// loader
export async function budgetLoader({ params }) {
const response = await fetch(`/api/budgets/${params.id}`);
const budget = await response.json();
if (!budget) {
throw new Error("The budget you’re trying to find doesn’t exist");
}
return { budget };
}
// action
export async function budgetAction({ request }) {
const data = await request.formData();
const { _action, ...values } = Object.fromEntries(data);
if (_action === "createExpense") {
try {
await createExpense({
name: values.newExpense,
amount: values.newExpenseAmount,
budgetId: values.newExpenseBudget,
category: values.newExpenseCategory,
currency: values.newExpenseCurrency
});
console.log(values, "what values are here in budget page")
return toast.success(`Added ${values.newExpense} to budget!`);
} catch (e) {
throw new Error("There was a problem creating your expense.");
}
}
if (_action === "deleteExpense") {
try {
deleteItem({
key: "expenses",
id: values.expenseId,
});
return toast.success("Expense deleted!");
} catch (e) {
throw new Error("There was a problem deleting your expense.");
}
}
}
const BudgetPage = () => {
const { budget } = useLoaderData();
const [loading, setLoading] = useState(true);
const [dots, setDots] = useState('.');
const [chart, setChart] = useState(null);
useEffect(() => {
const initializeChart = () => {
console.log("Initializing chart...");
// Extract data from expenses for the initial chart
const chartData = budget.expenses.map((expense) => [
expense.name,
expense.amount,
]);
console.log("Chart data:", chartData);
const newChart = c3.generate({
bindto: '#chart', // Specify the element where the chart will be rendered
data: {
columns: chartData,
type: 'donut',
onclick: function (d, i) {
console.log('onclick', d, i);
},
onmouseover: function (d, i) {
console.log('onmouseover', d, i);
},
onmouseout: function (d, i) {
console.log('onmouseout', d, i);
},
},
donut: {
title: 'Expenses Distribution',
},
});
console.log("Chart initialized:", newChart);
// Unload some data after another delay (2500 milliseconds in this example)
setTimeout(() => {
const idsToUnload = budget.expenses.slice(0, 2).map((expense) => expense.id);
newChart.unload({
ids: idsToUnload,
});
console.log("Data unloaded from chart:", idsToUnload);
}, 2500);
setChart(newChart); // Set the chart instance in the state
};
// Invoke the initializeChart function
initializeChart();
}, [budget.expenses]);
useEffect(() => {
const timer = setTimeout(() => {
setLoading(false);
}, 3000);
return () => clearTimeout(timer);
}, []);
useEffect(() => {
if (loading) {
const dotsTimer = setInterval(() => {
setDots((prevDots) => (prevDots.length >= 3 ? '.' : prevDots + '.'));
}, 500);
return () => clearInterval(dotsTimer);
}
}, [loading]);
if (loading || !budget) {
return (
<div
className="grid-lg"
style={{
color: 'hsl(var(--accent))',
fontWeight: 'bold',
fontSize: 'clamp(1.94rem, calc(1.56rem + 1.92vw), 2.93rem)',
display: 'flex',
alignItems: 'center',
}}
>
<img src={LoadingSpin} alt="Loading" width="40px" />
Loading{dots}
</div>
);
}
return (
<div
className="grid-lg"
style={{
"--accent": budget.color,
}}
>
<h1 className="h2">
<span className="accent">{budget.name}</span> Overview
</h1>
<div className="flex-lg">
<BudgetItem budget={budget} showDelete={true}/>
<AddExpenseForm budgets={[budget]} />
</div>
{budget.expenses && budget.expenses.length > 0 ? (
<div className="grid-md">
<h2>
<span className="accent">{budget.name}</span> Expenses
</h2>
{chart && <div id="chart">{chart}</div>}
<Table expenses={budget.expenses} showBudget={false} />
</div>
) : (
<div
className="grid-lg"
style={{
color: "hsl(var(--accent))",
fontWeight: "bold",
fontSize: "clamp(1.94rem, calc(1.56rem + 1.92vw), 2.93rem)"
}}
>
<p>{budget.name} has no expenses</p>
</div>
)}
</div>
);
};
export default BudgetPage;