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



This content originally appeared on DEV Community and was authored by Daniel Lawal

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
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>
  );
}

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' }} />;
}

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>
  );
}

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!


This content originally appeared on DEV Community and was authored by Daniel Lawal