Building dashboards shouldn’t require a PhD in hydration debugging
Picture this: It’s 2 AM, you’re staring at your screen, and your “simple” bar chart is throwing hydration errors again. The client-side JavaScript doesn’t match the server-rendered HTML, users are seeing content flicker, and your beautifully crafted dashboard looks like it’s having an existential crisis.
You've been here if you’ve ever tried to use ECharts with React and Next.js. I certainly have — more times than I’d like to admit.
After years of building dashboards and encountering the same problems over and over again, I finally decided to solve this once and for all. The result? react-echarts-kit — a production-ready, SSR-safe charting toolkit that eliminates all the pain points I’ve collected over the years.
I’ve been building data visualization tools for companies ranging from startups to Fortune 500s, and regardless of the tech stack, the same issues always surface:
ECharts isn’t SSR-friendly. It’s a fantastic charting library, but it was built for the browser. When you try to render it on the server, things break spectacularly.
Chart setup becomes scattered. Every developer on the team creates their wrapper components, utility functions, and workarounds. Soon, you have five different ways to create a bar chart across your codebase.
The boilerplate is crushing. Want to add a simple chart? Get ready to write 60+ lines of setup code, handle SSR manually, manage cleanup, add resize listeners, and pray everything works together.
Let me show you what I mean.
Here’s what you had to write every single time you wanted a simple bar chart in Next.js:
import { useEffect, useRef, useState } from 'react';
import * as echarts from 'echarts';
export default function Dashboard() {
const chartRef = useRef<HTMLDivElement>(null);
const chartInstance = useRef<echarts.ECharts | null>(null);
const [isClient, setIsClient] = useState(false);
// Handle SSR - this is where things get tricky
useEffect(() => {
setIsClient(true);
}, []);
useEffect(() => {
if (!isClient || !chartRef.current) return;
// Initialize chart
chartInstance.current = echarts.init(chartRef.current);
// Define options - lots of boilerplate here
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: ['Jan', 'Feb', 'Mar'],
axisTick: {
alignWithLabel: true
}
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: 'Value',
type: 'bar',
barWidth: '60%',
data: [400, 300, 500]
}
]
};
chartInstance.current.setOption(option);
// Handle resize manually
const handleResize = () => {
chartInstance.current?.resize();
};
window.addEventListener('resize', handleResize);
// Don't forget cleanup - memory leaks are waiting
return () => {
window.removeEventListener('resize', handleResize);
chartInstance.current?.dispose();
};
}, [isClient]);
// Theme changes? Start over.
useEffect(() => {
if (chartInstance.current) {
chartInstance.current.dispose();
chartInstance.current = echarts.init(chartRef.current!, 'dark');
// Re-set all options again...
}
}, [/* theme dependency */]);
// Loading state for SSR
if (!isClient) {
return <div style={{ height: '400px', backgroundColor: '#f5f5f5' }}>Loading chart...</div>;
}
return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />;
}
60+ lines of code for a simple bar chart. And that’s just the beginning.
Every developer who touched this code had to understand:
Multiply this by every chart in your application, and you’ve got a maintenance nightmare.
The final straw came during a project where we had over 20 different chart components across the app. Each one was slightly different. Some handled themes, others didn’t. Some were responsive, others broke on mobile. The bug reports kept coming:
We were spending more time debugging charts than building features. Something had to change.
I started with a simple goal: What if creating a chart was as easy as using any other React component?
No setup. No SSR workarounds. No manual cleanup. Just pass your data and get a beautiful, responsive chart.
Here’s what I built:
import { BarChart, ThemeProvider, lightTheme } from 'react-echarts-kit/ssr';
export default function Dashboard() {
const data = {
categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
series: [
{
name: 'Sales',
data: [120, 200, 150, 80, 70],
color: '#5470c6',
},
{
name: 'Revenue',
data: [220, 182, 191, 234, 290],
color: '#91cc75',
},
],
};
return (
<ThemeProvider defaultTheme="light">
<BarChart data={data} width="100%" height={400} />
</ThemeProvider>
);
}
Six lines instead of sixty. The same chart, but actually maintainable.
Every component uses dynamic imports with proper loading states. No more hydration errors, no more content flicker. It just works.
Instead of reinventing the wheel every time, you get pre-built components for the charts you actually need:
For more advanced use cases, you get utilities that handle the heavy lifting:
useResponsiveChart
- Automatic resizinguseChartData
- Data transformation helpersuseChartTheme
- Dynamic theme managementLight and dark mode support with zero configuration. Switch themes and watch all your charts update automatically.
Strongly typed props mean fewer runtime errors and better IntelliSense. Your IDE actually helps you build charts correctly.
Since releasing react-echarts-kit internally at my company, we’ve seen:
90% reduction in chart-related bug reports. When the foundation is solid, everything built on top is more reliable.
Faster feature development. Developers spend time building business logic instead of debugging hydration issues.
Consistent user experience. Every chart looks and behaves the same way across the entire application.
Easier onboarding. New developers can add charts without learning the intricacies of SSR patterns.
The library is live on npm and actively maintained. I’m looking for feedback from developers who’ve fought similar battles with client-side libraries in SSR environments.
Package: https://www.npmjs.com/package/react-echarts-kit
Some questions I’m exploring:
This isn’t just about charts. It’s about recognizing when the development community keeps solving the same problem over and over again, and building better abstractions.
Every time a developer spends hours debugging hydration errors for a simple bar chart, that’s time not spent building the features users actually need. Every time a team creates their fifth slightly-different chart wrapper, that’s technical debt accumulating.
Sometimes the best code you can write is the code that prevents others from having to write code at all.
Payroll Compliance Checklist and Tax Law Guide for 2025
Highlight the critical nature of staying informed on payroll compliance and tax laws for tech companies with a global footprint in 2025.
How Much Software Engineers Make in 2025?
We will delve into the various factors that influence software engineer salaries in 2025, provide detailed salary breakdowns by region, and explore how remote work is shaping compensation trends.
The Future of Remote Work: Trends and Predictions for 2025 and Beyond
Remote work is no longer just a trend; it's becoming a standard practice in the global workforce.
Payroll Compliance Checklist and Tax Law Guide for 2025
Highlight the critical nature of staying informed on payroll compliance and tax laws for tech companies with a global footprint in 2025.
How Much Software Engineers Make in 2025?
We will delve into the various factors that influence software engineer salaries in 2025, provide detailed salary breakdowns by region, and explore how remote work is shaping compensation trends.
The Future of Remote Work: Trends and Predictions for 2025 and Beyond
Remote work is no longer just a trend; it's becoming a standard practice in the global workforce.