DEV Community

Cover image for React-echarts-kit: SSR-Safe Chart Components for React & Next.js
Daniel Lawal
Daniel Lawal

Posted on

React-echarts-kit: SSR-Safe Chart Components for React & Next.js

React-echarts-kit

A production-ready, SSR-safe charting toolkit for React and Next.js

The Problem

I've been building dashboards for years, and I always run into the same issues when using ECharts in React/Next.js:

  • ❌ ECharts isn't SSR-friendly out of the box
  • ❌ Chart setup ends up scattered across components
  • ❌ Team members reinvent the wheel every time they need a chart

The Solution

react-echarts-kit solves these pain points with a comprehensive charting toolkit designed specifically for server-rendered React applications.

What Makes It Different

🚀 SSR-Safe Components

Built-in dynamic imports with loading states for Next.js. No more hydration errors or layout shifts.

📊 Common Chart Types Included

Ready-to-use components for the most common use cases:

  • Bar charts
  • Line charts
  • Pie charts
  • Area charts
  • Gauge charts
  • Plus a flexible ChartContainer for custom implementations

🎣 Powerful Hooks

  • useResponsiveChart - Automatic chart resizing
  • useChartData - Data transformation utilities
  • useChartTheme - Dynamic theme management

🎨 Built-in Theme System

Light/Dark mode support out of the box with ThemeProvider. Consistent styling across all charts.

🔷 TypeScript-First

Strongly typed props and interfaces for better developer experience and fewer runtime errors.

⚡ Zero-Config Defaults

Sensible chart options to get started quickly, while remaining fully customizable for advanced use cases.

Quick Start

npm install react-echarts-kit
# or
yarn add react-echarts-kit
Enter fullscreen mode Exit fullscreen mode
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>
  );
}
Enter fullscreen mode Exit fullscreen mode

The Old Way vs. The New Way

😰 Before: Raw ECharts in React/Next.js

Here's what you had to deal with every single time:

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
  useEffect(() => {
    setIsClient(true);
  }, []);

  useEffect(() => {
    if (!isClient || !chartRef.current) return;

    // Initialize chart
    chartInstance.current = echarts.init(chartRef.current);

    // Define options
    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
    const handleResize = () => {
      chartInstance.current?.resize();
    };

    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
      chartInstance.current?.dispose();
    };
  }, [isClient]);

  // Handle theme changes
  useEffect(() => {
    if (chartInstance.current) {
      // Manually update theme...
      chartInstance.current.dispose();
      chartInstance.current = echarts.init(chartRef.current!, 'dark');
      // Re-set options...
    }
  }, [/* theme dependency */]);

  if (!isClient) {
    return <div style={{ height: '400px', backgroundColor: '#f5f5f5' }}>Loading chart...</div>;
  }

  return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />;
}
Enter fullscreen mode Exit fullscreen mode

Problems with this approach:

  • 🤮 60+ lines of boilerplate for a simple bar chart
  • 🐛 Manual SSR handling - easy to get wrong
  • 🔧 Manual cleanup - memory leaks waiting to happen
  • 📱 Manual responsiveness - window resize listeners everywhere
  • 🎨 Manual theme switching - dispose and recreate charts
  • 🔄 Repetitive code - copy-paste this for every chart
  • ⚠️ Hydration issues - one small mistake breaks everything

😌 After: react-echarts-kit

The same chart, but actually maintainable:

import { BarChart, ThemeProvider, lightTheme } from 'react-echarts-kit';

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

What you get:

  • 6 lines instead of 60+
  • SSR handled automatically
  • Auto-cleanup on unmount
  • Responsive by default
  • Theme switching just works
  • Reusable everywhere
  • Zero hydration issues

Why This Library?

If you've ever tried integrating ECharts into a server-rendered React app, you know the pain. react-echarts-kit eliminates all the boilerplate while staying flexible enough to drop into existing codebases.

Links

Contributing & Feedback

I'd love feedback — especially from developers who've dealt with SSR and heavy client-side libraries:

  • Does this solve the main pain points you've experienced?
  • What chart types or hooks would you want to see next?
  • How can we improve the developer experience?

Feel free to open issues, submit PRs, or start discussions in the repository!

Top comments (0)