Render all chartjs charts in react typescript tailwindcss projects
In this tutorial, we'll show you how to render all chartjs charts in React project.
Table of Contents
- Define all chartjs charts
- Write a funcitonal component
- Write a chartjs wrapper
- Final Code
- Demo
- Optimize
Define all chartjs charts
We copy all chartjs official example codes and put them in component/chartjsofficial
directory. We also define title and component for each example chart.
import { VerticalBarChart } from "@/component/chartjsofficial/verticalbarchart";
import { HorizontalBarChart } from "@/component/chartjsofficial/horizontalbarchart";
import { StackedBarChart } from "@/component/chartjsofficial/stackedbarchart";
import { GroupedBarChart } from "@/component/chartjsofficial/groupedbarchart";
import { AreaChart } from "@/component/chartjsofficial/areachart";
import { LineChart } from "@/component/chartjsofficial/linechart";
import { MultiAxisLineChart } from "@/component/chartjsofficial/multiaxislinechart";
import { PieChart } from "@/component/chartjsofficial/piechart";
import { DoughnutChart } from "@/component/chartjsofficial/doughnutchart";
import { PolarAreaChart } from "@/component/chartjsofficial/polarareachart";
import { RadarChart } from "@/component/chartjsofficial/radarchart";
import { ScatterChart } from "@/component/chartjsofficial/scatterchart";
import { BubbleChart } from "@/component/chartjsofficial/bubblechart";
import { MultiTypeChart } from "@/component/chartjsofficial/multitypechart";
import { ChartEvents } from "@/component/chartjsofficial/chartevents";
import { ChartRef } from "@/component/chartjsofficial/chartref";
import { GradientChart } from "@/component/chartjsofficial/gradientchart";
import { ChartEventsSingleDataset } from "@/component/chartjsofficial/charteventssingledataset";
import { ChartEventsSingleDatasetOutsideDatasource } from "@/component/chartjsofficial/charteventssingledatasetoutsidedatasource";
const components = [
{
title: "VerticalBarChart",
component: VerticalBarChart,
},
{
title: "HorizontalBarChart",
component: HorizontalBarChart,
},
{
title: "StackedBarChart",
component: StackedBarChart,
},
{
title: "GroupedBarChart",
component: GroupedBarChart,
},
{
title: "AreaChart",
component: AreaChart,
},
{
title: "LineChart",
component: LineChart,
},
{
title: "MultiAxisLineChart",
component: MultiAxisLineChart,
},
{
title: "DoughnutChart",
component: DoughnutChart,
},
{
title: "PolarAreaChart",
component: PolarAreaChart,
},
{
title: "RadarChart",
component: RadarChart,
},
{
title: "ScatterChart",
component: ScatterChart,
},
{
title: "BubbleChart",
component: BubbleChart,
},
{
title: "ScatterChart",
component: ScatterChart,
},
{
title: "MultiTypeChart",
component: MultiTypeChart,
},
{
title: "ChartEvents",
component: ChartEvents,
},
{
title: "ChartRef",
component: ChartRef,
},
{
title: "GradientChart",
component: GradientChart,
},
{
title: "ChartEventsSingleDataset",
component: ChartEventsSingleDataset,
},
];
Write a funcitonal component
In order to render all components, we write a functional component to take array of component with title and render them in one place.
type Component = {
title: string,
component: React.FunctionComponent,
};
type ChartProps = {
components: Component[],
};
const ComponentWrapper: React.FC<ChartProps> = ({ components }) => {
return (
<div>
{components.map((component, index) => {
return (
<ChartWrapper key={index} title={component.title}>
<component.component />
</ChartWrapper>
);
})}
</div>
);
};
Write a chartjs wrapper
In order to add title for each chart, we write a functional component to wrapper up every chart with a h1
. Note we define the h1
style using tailwindcss, setting div size(h-96
) and text size(text-3xl
), etc.
export const ChartWrapper: React.FC<{
title: string,
children: React.ReactNode,
}> = ({ title, children }) => {
return (
<div className="max-h-96 h-96 bg-slate-50 border border-dashed">
<h1 className="text-3xl text-center font-bold underline">{title}</h1>
{children}
</div>
);
};
Final Code
First, import all chartjs components and define components to render.
import { VerticalBarChart } from "@/component/chartjsofficial/verticalbarchart";
import { HorizontalBarChart } from "@/component/chartjsofficial/horizontalbarchart";
import { StackedBarChart } from "@/component/chartjsofficial/stackedbarchart";
import { GroupedBarChart } from "@/component/chartjsofficial/groupedbarchart";
import { AreaChart } from "@/component/chartjsofficial/areachart";
import { LineChart } from "@/component/chartjsofficial/linechart";
import { MultiAxisLineChart } from "@/component/chartjsofficial/multiaxislinechart";
import { PieChart } from "@/component/chartjsofficial/piechart";
import { DoughnutChart } from "@/component/chartjsofficial/doughnutchart";
import { PolarAreaChart } from "@/component/chartjsofficial/polarareachart";
import { RadarChart } from "@/component/chartjsofficial/radarchart";
import { ScatterChart } from "@/component/chartjsofficial/scatterchart";
import { BubbleChart } from "@/component/chartjsofficial/bubblechart";
import { MultiTypeChart } from "@/component/chartjsofficial/multitypechart";
import { ChartEvents } from "@/component/chartjsofficial/chartevents";
import { ChartRef } from "@/component/chartjsofficial/chartref";
import { GradientChart } from "@/component/chartjsofficial/gradientchart";
import { ChartEventsSingleDataset } from "@/component/chartjsofficial/charteventssingledataset";
import { ChartEventsSingleDatasetOutsideDatasource } from "@/component/chartjsofficial/charteventssingledatasetoutsidedatasource";
const components = [
{
title: "VerticalBarChart",
component: VerticalBarChart,
},
{
title: "HorizontalBarChart",
component: HorizontalBarChart,
},
{
title: "StackedBarChart",
component: StackedBarChart,
},
{
title: "GroupedBarChart",
component: GroupedBarChart,
},
{
title: "AreaChart",
component: AreaChart,
},
{
title: "LineChart",
component: LineChart,
},
{
title: "MultiAxisLineChart",
component: MultiAxisLineChart,
},
{
title: "DoughnutChart",
component: DoughnutChart,
},
{
title: "PolarAreaChart",
component: PolarAreaChart,
},
{
title: "RadarChart",
component: RadarChart,
},
{
title: "ScatterChart",
component: ScatterChart,
},
{
title: "BubbleChart",
component: BubbleChart,
},
{
title: "ScatterChart",
component: ScatterChart,
},
{
title: "MultiTypeChart",
component: MultiTypeChart,
},
{
title: "ChartEvents",
component: ChartEvents,
},
{
title: "ChartRef",
component: ChartRef,
},
{
title: "GradientChart",
component: GradientChart,
},
{
title: "ChartEventsSingleDataset",
component: ChartEventsSingleDataset,
},
];
Next, write a function called ChartWrapper
to wrapper up react chartjs chart components with a h1
as the title.
export const ChartWrapper: React.FC<{
title: string,
children: React.ReactNode,
}> = ({ title, children }) => {
return (
<div className="max-h-96 h-96 bg-slate-50 border border-dashed">
<h1 className="text-3xl text-center font-bold underline">{title}</h1>
{children}
</div>
);
};
Then, write a functional component to take a arrays of components and render them use ChartWrapper
component.
type Component = {
title: string,
component: React.FunctionComponent,
};
type ChartProps = {
components: Component[],
};
const ComponentWrapper: React.FC<ChartProps> = ({ components }) => {
return (
<div>
{components.map((component, index) => {
return (
<ChartWrapper key={index} title={component.title}>
<component.component />
</ChartWrapper>
);
})}
</div>
);
};
Finally, in App
component, we iterate the components and render them in a div with grid
class.
export default function App() {
return (
<div>
<Head>
<title>ChartJS + NextJS + TailwindCSS</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<div className={styles.description}>
<h1 className="text-3xl text-center font-bold underline">
ChartJS + NextJS + TailwindCSS
</h1>
<div className="container columns-2">
<div className="grid grid-cols-2 md:grid-cols-1 gap-0">
{<ComponentWrapper components={components} />}
</div>
</div>
</div>
</main>
</div>
);
}
Demo
Optimize
Note, for ComponentWrapper
function component, it's more verbose. We could write it in another way.
Here is the old way.
// NOTE: OK but verbose
const ComponentWrapper: React.FC<ChartProps> = ({ components }) => {
return (
<div>
{components.map((c, index) => {
return (
<ChartWrapper key={index} title={c.title}>
<c.component />
</ChartWrapper>
);
})}
</div>
);
};
The new way:
// NOTE: concise
const ComponentWrapperChatGPTAgain: React.FC<ChartProps> = ({ components }) => {
return (
<div>
{components.map((c, index) => {
const { title, component: C } = c;
return (
<ChartWrapper key={index} title={title}>
<C />
</ChartWrapper>
);
})}
</div>
);
};
To render list of charts components with titles and properties, we wrote two React component functions. While both functions produce the same output, their implementation approaches are different.
The first function ComponentWrapper
is a good method, but the downside is that it is quite verbose. It uses curly braces and a return statement to wrap the component inside <ChartWrapper>
, and it also references c.title
and c.component
multiple times within the function body.
The second function ComponentWrapperChatGPTAgain
is a more concise implementation. It uses ES6 destructuring syntax to get title and component from the components object, which avoids repeated use of c.title
and c.component
. Additionally, it uses a more descriptive variable name C
for the component.
Clearly, the second implementation is more succinct, easier to read and maintain, and also makes it easier to add new properties or methods. Therefore, we recommend using the second function ComponentWrapperChatGPTAgain
as a more efficient programming practice.
To summarize, the primary difference between these two implementation methods is that the first one is verbose, which makes it difficult to read and maintain, while the second one is more concise and easier to read and maintain. The second function also uses destructuring, which is a useful syntax for improving readability by eliminating repetition. By using a more concise and readable implementation, you can streamline your code and make it more efficient.
chatgpt says
Comparing Two React Component Functions
In this post, we will compare and contrast two React component functions that are used to render a list of chart components with titles and properties. While both functions ultimately produce the same result, their implementation approaches are different.
Function 1: ComponentWrapper
const ComponentWrapper: React.FC<ChartProps> = ({ components }) => {
return (
<div>
{components.map((c, index) => {
return (
<ChartWrapper key={index} title={c.title}>
<c.component />
</ChartWrapper>
);
})}
</div>
);
};
This function is a good approach, but it is quite verbose. It uses curly braces and a return statement to wrap the component inside <ChartWrapper>
, and it also references c.title
and c.component
multiple times within the function body. It might be a bit difficult to read and maintain for developers, especially with more complex components.
Function 2: ComponentWrapperChatGPTAgain
const ComponentWrapperChatGPTAgain: React.FC<ChartProps> = ({ components }) => {
return (
<div>
{components.map((c, index) => {
const { title, component: C } = c;
return (
<ChartWrapper key={index} title={title}>
<C />
</ChartWrapper>
);
})}
</div>
);
};
This function, on the other hand, is a more concise implementation. It uses ES6 destructuring syntax to get title and component from the components object, which avoids repeated use of c.title
and c.component
. Additionally, it uses a more descriptive variable name C
for the component.
The second implementation is more succinct, easier to read and maintain, and also makes it easier to add new properties or methods in the future. Therefore, we recommend using the second function ComponentWrapperChatGPTAgain
as a more efficient programming practice.
Conclusion
The primary difference between these two implementation methods is that the first one is verbose, which makes it difficult to read and maintain, while the second one is more concise and easier to read and maintain. The second function also uses destructuring, which is a useful syntax for improving readability by eliminating repetition. By using a concise, readable implementation, code can be streamlined and more efficient.