Recharts + Next.js App Router : construire des tableaux de bord interactifs de visualisation de données

Noqta Team
Par Noqta Team ·

Chargement du lecteur de synthèse vocale...

Les données racontent une histoire — les graphiques la rendent inoubliable. Recharts est la bibliothèque de graphiques React-native la plus populaire, construite sur des composants composables et alimentée par D3 en arrière-plan. Dans ce tutoriel, vous construirez un tableau de bord complet d'analyse des ventes avec Next.js 15 App Router, couvrant chaque type de graphique et chaque pattern nécessaire en production.

Ce que vous allez apprendre

À la fin de ce tutoriel, vous saurez :

  • Configurer Recharts dans un projet Next.js 15 App Router avec TypeScript
  • Construire des graphiques en barres, en lignes, en aires et circulaires de zéro
  • Créer des infobulles personnalisées et des légendes interactives
  • Rendre les graphiques entièrement responsives avec ResponsiveContainer
  • Récupérer et afficher des données dynamiques depuis des routes API
  • Ajouter des animations fluides et des interactions au survol
  • Prendre en charge le mode sombre avec des couleurs de graphiques adaptatives
  • Organiser le tout dans une mise en page de tableau de bord prête pour la production

Prérequis

Avant de commencer, assurez-vous de disposer de :

  • Node.js 20+ installé (node --version)
  • Une expérience en TypeScript (types, interfaces, génériques)
  • Une familiarité avec les bases de Next.js App Router (layouts, pages, composants client/serveur)
  • Une compréhension basique de Tailwind CSS pour la mise en page

Pourquoi Recharts en 2026 ?

En matière de graphiques en React, plusieurs bibliothèques se disputent la première place. Voici pourquoi Recharts reste le meilleur choix :

FonctionnalitéRechartsChart.js (react-chartjs-2)NivoVictory
Composants React natifsOuiWrapperOuiOui
Taille du bundle~45 KB~60 KB~50 KB~55 KB
ComposabilitéExcellenteLimitéeBonneBonne
Support TypeScriptIntégréPartielIntégréIntégré
Compatibilité SSROuiCanvas (limité)OuiOui
PersonnalisationAu niveau composantObjet de configPropsProps
Courbe d'apprentissageFaibleFaibleModéréeModérée

Recharts se distingue parce que chaque élément — axes, grilles, infobulles, légendes — est un composant React que vous pouvez composer, styliser et étendre. Si vous connaissez React, vous savez déjà utiliser Recharts.


Étape 1 : configuration du projet

Créez un nouveau projet Next.js 15 avec TypeScript et Tailwind CSS :

npx create-next-app@latest sales-dashboard --typescript --tailwind --app --src-dir
cd sales-dashboard

Installez Recharts :

npm install recharts

Votre structure de projet devrait ressembler à ceci :

sales-dashboard/
├── src/
│   ├── app/
│   │   ├── layout.tsx
│   │   ├── page.tsx
│   │   └── api/
│   │       └── sales/
│   │           └── route.ts
│   ├── components/
│   │   └── charts/
│   │       ├── BarChartCard.tsx
│   │       ├── LineChartCard.tsx
│   │       ├── AreaChartCard.tsx
│   │       ├── PieChartCard.tsx
│   │       └── CustomTooltip.tsx
│   └── lib/
│       └── data.ts
├── package.json
└── tsconfig.json

Étape 2 : définir la couche de données

Créez src/lib/data.ts avec des données typées pour votre tableau de bord :

export interface MonthlySales {
  month: string;
  revenue: number;
  orders: number;
  customers: number;
}
 
export interface ProductSales {
  name: string;
  value: number;
  color: string;
}
 
export const monthlySalesData: MonthlySales[] = [
  { month: "Jan", revenue: 4200, orders: 180, customers: 120 },
  { month: "Fév", revenue: 5100, orders: 210, customers: 145 },
  { month: "Mar", revenue: 4800, orders: 195, customers: 130 },
  { month: "Avr", revenue: 6300, orders: 270, customers: 180 },
  { month: "Mai", revenue: 5900, orders: 250, customers: 165 },
  { month: "Juin", revenue: 7200, orders: 310, customers: 210 },
  { month: "Juil", revenue: 6800, orders: 290, customers: 195 },
  { month: "Août", revenue: 7500, orders: 320, customers: 225 },
  { month: "Sep", revenue: 8100, orders: 350, customers: 240 },
  { month: "Oct", revenue: 7800, orders: 335, customers: 230 },
  { month: "Nov", revenue: 9200, orders: 400, customers: 280 },
  { month: "Déc", revenue: 10500, orders: 450, customers: 320 },
];
 
export const productSalesData: ProductSales[] = [
  { name: "Électronique", value: 35, color: "#6366f1" },
  { name: "Vêtements", value: 25, color: "#8b5cf6" },
  { name: "Maison & Jardin", value: 20, color: "#a78bfa" },
  { name: "Sport", value: 12, color: "#c4b5fd" },
  { name: "Livres", value: 8, color: "#ddd6fe" },
];

Cela vous donne deux jeux de données : des ventes mensuelles en série temporelle et une répartition par catégorie de produits. Les deux sont entièrement typés pour la sécurité TypeScript.


Étape 3 : construire un graphique en barres

Créez src/components/charts/BarChartCard.tsx. Le graphique en barres affichera le chiffre d'affaires mensuel :

"use client";
 
import {
  BarChart,
  Bar,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
} from "recharts";
import { MonthlySales } from "@/lib/data";
 
interface BarChartCardProps {
  data: MonthlySales[];
}
 
export default function BarChartCard({ data }: BarChartCardProps) {
  return (
    <div className="rounded-xl border bg-white p-6 shadow-sm dark:bg-gray-900 dark:border-gray-800">
      <h3 className="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
        Chiffre d'affaires mensuel
      </h3>
      <ResponsiveContainer width="100%" height={300}>
        <BarChart data={data} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" />
          <XAxis
            dataKey="month"
            tick={{ fontSize: 12, fill: "#6b7280" }}
            axisLine={{ stroke: "#d1d5db" }}
          />
          <YAxis
            tick={{ fontSize: 12, fill: "#6b7280" }}
            axisLine={{ stroke: "#d1d5db" }}
            tickFormatter={(value) => `${value / 1000}k$`}
          />
          <Tooltip
            formatter={(value: number) => [`${value.toLocaleString()}$`, "CA"]}
            contentStyle={{
              backgroundColor: "#1f2937",
              border: "none",
              borderRadius: "8px",
              color: "#f9fafb",
            }}
          />
          <Bar
            dataKey="revenue"
            fill="#6366f1"
            radius={[4, 4, 0, 0]}
            animationDuration={800}
          />
        </BarChart>
      </ResponsiveContainer>
    </div>
  );
}

Points clés :

  • ResponsiveContainer enveloppe chaque graphique pour le rendre responsive. Définissez toujours width="100%" et une hauteur fixe.
  • CartesianGrid avec strokeDasharray crée des lignes de grille en pointillés subtils.
  • radius sur Bar arrondit les coins supérieurs pour un look moderne.
  • tickFormatter sur YAxis formate les grands nombres en 4k$, 8k$, etc.

Étape 4 : construire un graphique en lignes

Créez src/components/charts/LineChartCard.tsx pour visualiser les tendances dans le temps :

"use client";
 
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";
import { MonthlySales } from "@/lib/data";
 
interface LineChartCardProps {
  data: MonthlySales[];
}
 
export default function LineChartCard({ data }: LineChartCardProps) {
  return (
    <div className="rounded-xl border bg-white p-6 shadow-sm dark:bg-gray-900 dark:border-gray-800">
      <h3 className="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
        Commandes vs Clients
      </h3>
      <ResponsiveContainer width="100%" height={300}>
        <LineChart data={data} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" />
          <XAxis
            dataKey="month"
            tick={{ fontSize: 12, fill: "#6b7280" }}
          />
          <YAxis tick={{ fontSize: 12, fill: "#6b7280" }} />
          <Tooltip
            contentStyle={{
              backgroundColor: "#1f2937",
              border: "none",
              borderRadius: "8px",
              color: "#f9fafb",
            }}
          />
          <Legend
            wrapperStyle={{ paddingTop: "12px" }}
            iconType="circle"
          />
          <Line
            type="monotone"
            dataKey="orders"
            stroke="#6366f1"
            strokeWidth={2}
            dot={{ fill: "#6366f1", r: 4 }}
            activeDot={{ r: 6, stroke: "#6366f1", strokeWidth: 2 }}
            animationDuration={1000}
            name="Commandes"
          />
          <Line
            type="monotone"
            dataKey="customers"
            stroke="#10b981"
            strokeWidth={2}
            dot={{ fill: "#10b981", r: 4 }}
            activeDot={{ r: 6, stroke: "#10b981", strokeWidth: 2 }}
            animationDuration={1200}
            name="Clients"
          />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}

Remarquez comment vous pouvez superposer plusieurs composants Line sur le même graphique. Chacun reçoit sa propre couleur, et le composant Legend récupère automatiquement les noms des dataKey. La propriété type="monotone" crée des courbes lisses au lieu d'angles aigus.


Étape 5 : construire un graphique en aires avec dégradés

Créez src/components/charts/AreaChartCard.tsx. Les graphiques en aires sont parfaits pour afficher le volume au fil du temps :

"use client";
 
import {
  AreaChart,
  Area,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
} from "recharts";
import { MonthlySales } from "@/lib/data";
 
interface AreaChartCardProps {
  data: MonthlySales[];
}
 
export default function AreaChartCard({ data }: AreaChartCardProps) {
  return (
    <div className="rounded-xl border bg-white p-6 shadow-sm dark:bg-gray-900 dark:border-gray-800">
      <h3 className="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
        Tendance du chiffre d'affaires
      </h3>
      <ResponsiveContainer width="100%" height={300}>
        <AreaChart data={data} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
          <defs>
            <linearGradient id="revenueGradient" x1="0" y1="0" x2="0" y2="1">
              <stop offset="5%" stopColor="#6366f1" stopOpacity={0.3} />
              <stop offset="95%" stopColor="#6366f1" stopOpacity={0} />
            </linearGradient>
          </defs>
          <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" />
          <XAxis
            dataKey="month"
            tick={{ fontSize: 12, fill: "#6b7280" }}
          />
          <YAxis
            tick={{ fontSize: 12, fill: "#6b7280" }}
            tickFormatter={(value) => `${value / 1000}k$`}
          />
          <Tooltip
            formatter={(value: number) => [`${value.toLocaleString()}$`, "CA"]}
            contentStyle={{
              backgroundColor: "#1f2937",
              border: "none",
              borderRadius: "8px",
              color: "#f9fafb",
            }}
          />
          <Area
            type="monotone"
            dataKey="revenue"
            stroke="#6366f1"
            strokeWidth={2}
            fill="url(#revenueGradient)"
            animationDuration={1000}
          />
        </AreaChart>
      </ResponsiveContainer>
    </div>
  );
}

Le secret réside dans les dégradés SVG. Le bloc defs définit un linearGradient qui passe de 30% d'opacité en haut à totalement transparent en bas. Le composant Area référence ce dégradé via fill="url(#revenueGradient)". Cela crée un look professionnel et soigné que les remplissages plats ne peuvent pas atteindre.


Étape 6 : construire un graphique circulaire

Créez src/components/charts/PieChartCard.tsx pour les données catégorielles :

"use client";
 
import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer, Legend } from "recharts";
import { ProductSales } from "@/lib/data";
 
interface PieChartCardProps {
  data: ProductSales[];
}
 
export default function PieChartCard({ data }: PieChartCardProps) {
  return (
    <div className="rounded-xl border bg-white p-6 shadow-sm dark:bg-gray-900 dark:border-gray-800">
      <h3 className="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
        Ventes par catégorie
      </h3>
      <ResponsiveContainer width="100%" height={300}>
        <PieChart>
          <Pie
            data={data}
            cx="50%"
            cy="50%"
            innerRadius={60}
            outerRadius={100}
            paddingAngle={3}
            dataKey="value"
            animationDuration={800}
            label={({ name, percent }) =>
              `${name} ${(percent * 100).toFixed(0)}%`
            }
            labelLine={{ stroke: "#6b7280" }}
          >
            {data.map((entry, index) => (
              <Cell key={`cell-${index}`} fill={entry.color} />
            ))}
          </Pie>
          <Tooltip
            formatter={(value: number) => [`${value}%`, "Part"]}
            contentStyle={{
              backgroundColor: "#1f2937",
              border: "none",
              borderRadius: "8px",
              color: "#f9fafb",
            }}
          />
          <Legend iconType="circle" />
        </PieChart>
      </ResponsiveContainer>
    </div>
  );
}

Définir innerRadius crée un graphique en anneau au lieu d'un camembert plein. Le paddingAngle ajoute des espaces subtils entre les tranches. Chaque composant Cell vous permet d'attribuer des couleurs individuelles à partir de vos données.


Étape 7 : construire une infobulle personnalisée

Les infobulles par défaut fonctionnent bien, mais les infobulles personnalisées vous donnent un contrôle total sur le design. Créez src/components/charts/CustomTooltip.tsx :

"use client";
 
interface CustomTooltipProps {
  active?: boolean;
  payload?: Array<{
    name: string;
    value: number;
    color: string;
  }>;
  label?: string;
}
 
export default function CustomTooltip({
  active,
  payload,
  label,
}: CustomTooltipProps) {
  if (!active || !payload || payload.length === 0) {
    return null;
  }
 
  return (
    <div className="rounded-lg border border-gray-200 bg-white px-4 py-3 shadow-lg dark:border-gray-700 dark:bg-gray-800">
      <p className="mb-2 text-sm font-medium text-gray-900 dark:text-white">
        {label}
      </p>
      {payload.map((item, index) => (
        <div key={index} className="flex items-center gap-2 text-sm">
          <span
            className="inline-block h-3 w-3 rounded-full"
            style={{ backgroundColor: item.color }}
          />
          <span className="text-gray-600 dark:text-gray-400">{item.name} :</span>
          <span className="font-semibold text-gray-900 dark:text-white">
            {typeof item.value === "number"
              ? item.value.toLocaleString()
              : item.value}
          </span>
        </div>
      ))}
    </div>
  );
}

Utilisez-la dans n'importe quel graphique en remplaçant le Tooltip intégré par :

<Tooltip content={<CustomTooltip />} />

L'infobulle personnalisée reçoit active, payload et label comme props de Recharts. Vous rendez le JSX que vous voulez — classes Tailwind, icônes, sparklines, tout ce que React peut rendre.


Étape 8 : créer une route API pour les données dynamiques

Dans un vrai tableau de bord, les données proviennent d'une API. Créez src/app/api/sales/route.ts :

import { NextResponse } from "next/server";
import { monthlySalesData, productSalesData } from "@/lib/data";
 
export async function GET() {
  // Simuler un délai API
  await new Promise((resolve) => setTimeout(resolve, 300));
 
  return NextResponse.json({
    monthly: monthlySalesData,
    products: productSalesData,
    summary: {
      totalRevenue: monthlySalesData.reduce((sum, m) => sum + m.revenue, 0),
      totalOrders: monthlySalesData.reduce((sum, m) => sum + m.orders, 0),
      totalCustomers: monthlySalesData.reduce((sum, m) => sum + m.customers, 0),
      avgOrderValue: Math.round(
        monthlySalesData.reduce((sum, m) => sum + m.revenue, 0) /
          monthlySalesData.reduce((sum, m) => sum + m.orders, 0)
      ),
    },
  });
}

Cette route API retourne toutes les données du tableau de bord en une seule requête. En production, vous remplaceriez les données statiques par des requêtes de base de données ou des appels API externes.


Étape 9 : assembler la page du tableau de bord

Maintenant, rassemblez tout dans src/app/page.tsx :

"use client";
 
import { useEffect, useState } from "react";
import BarChartCard from "@/components/charts/BarChartCard";
import LineChartCard from "@/components/charts/LineChartCard";
import AreaChartCard from "@/components/charts/AreaChartCard";
import PieChartCard from "@/components/charts/PieChartCard";
import { MonthlySales, ProductSales } from "@/lib/data";
 
interface DashboardData {
  monthly: MonthlySales[];
  products: ProductSales[];
  summary: {
    totalRevenue: number;
    totalOrders: number;
    totalCustomers: number;
    avgOrderValue: number;
  };
}
 
export default function DashboardPage() {
  const [data, setData] = useState<DashboardData | null>(null);
  const [loading, setLoading] = useState(true);
 
  useEffect(() => {
    fetch("/api/sales")
      .then((res) => res.json())
      .then((json) => {
        setData(json);
        setLoading(false);
      });
  }, []);
 
  if (loading || !data) {
    return (
      <div className="flex min-h-screen items-center justify-center">
        <div className="h-8 w-8 animate-spin rounded-full border-4 border-indigo-500 border-t-transparent" />
      </div>
    );
  }
 
  const stats = [
    { label: "CA Total", value: `${data.summary.totalRevenue.toLocaleString()}$` },
    { label: "Commandes", value: data.summary.totalOrders.toLocaleString() },
    { label: "Clients", value: data.summary.totalCustomers.toLocaleString() },
    { label: "Panier moyen", value: `${data.summary.avgOrderValue}$` },
  ];
 
  return (
    <main className="min-h-screen bg-gray-50 p-6 dark:bg-gray-950">
      <div className="mx-auto max-w-7xl">
        <h1 className="mb-8 text-3xl font-bold text-gray-900 dark:text-white">
          Tableau de bord des ventes
        </h1>
 
        {/* Cartes de résumé */}
        <div className="mb-8 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
          {stats.map((stat) => (
            <div
              key={stat.label}
              className="rounded-xl border bg-white p-6 shadow-sm dark:bg-gray-900 dark:border-gray-800"
            >
              <p className="text-sm text-gray-500 dark:text-gray-400">
                {stat.label}
              </p>
              <p className="mt-1 text-2xl font-bold text-gray-900 dark:text-white">
                {stat.value}
              </p>
            </div>
          ))}
        </div>
 
        {/* Grille de graphiques */}
        <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
          <BarChartCard data={data.monthly} />
          <LineChartCard data={data.monthly} />
          <AreaChartCard data={data.monthly} />
          <PieChartCard data={data.products} />
        </div>
      </div>
    </main>
  );
}

Cette page récupère les données depuis l'API, affiche des statistiques de synthèse dans la rangée supérieure, et rend les quatre types de graphiques dans une grille responsive à 2 colonnes. Sur mobile, les graphiques se superposent verticalement grâce au breakpoint lg:grid-cols-2.


Étape 10 : ajouter le support du mode sombre

Recharts n'a pas de mode sombre intégré, mais vous pouvez le rendre adaptatif au thème en utilisant des variables CSS ou un contexte React. Voici une approche légère avec un hook personnalisé :

// src/lib/useChartTheme.ts
"use client";
 
import { useEffect, useState } from "react";
 
export interface ChartTheme {
  gridColor: string;
  tickColor: string;
  tooltipBg: string;
  tooltipText: string;
}
 
const lightTheme: ChartTheme = {
  gridColor: "#e5e7eb",
  tickColor: "#6b7280",
  tooltipBg: "#1f2937",
  tooltipText: "#f9fafb",
};
 
const darkTheme: ChartTheme = {
  gridColor: "#374151",
  tickColor: "#9ca3af",
  tooltipBg: "#f9fafb",
  tooltipText: "#1f2937",
};
 
export function useChartTheme(): ChartTheme {
  const [isDark, setIsDark] = useState(false);
 
  useEffect(() => {
    const mq = window.matchMedia("(prefers-color-scheme: dark)");
    setIsDark(mq.matches);
    const handler = (e: MediaQueryListEvent) => setIsDark(e.matches);
    mq.addEventListener("change", handler);
    return () => mq.removeEventListener("change", handler);
  }, []);
 
  return isDark ? darkTheme : lightTheme;
}

Puis utilisez le thème dans vos composants de graphiques :

import { useChartTheme } from "@/lib/useChartTheme";
 
export default function BarChartCard({ data }: BarChartCardProps) {
  const theme = useChartTheme();
 
  return (
    <ResponsiveContainer width="100%" height={300}>
      <BarChart data={data}>
        <CartesianGrid strokeDasharray="3 3" stroke={theme.gridColor} />
        <XAxis tick={{ fill: theme.tickColor }} />
        <YAxis tick={{ fill: theme.tickColor }} />
        <Tooltip
          contentStyle={{
            backgroundColor: theme.tooltipBg,
            color: theme.tooltipText,
          }}
        />
        <Bar dataKey="revenue" fill="#6366f1" />
      </BarChart>
    </ResponsiveContainer>
  );
}

Maintenant, vos graphiques s'adaptent automatiquement lorsque l'utilisateur bascule entre le mode clair et le mode sombre.


Étape 11 : optimisation des performances

Lors du rendu de nombreux graphiques sur une seule page, gardez ces conseils en tête :

Chargement différé des graphiques sous la ligne de flottaison

Ne rendez les graphiques que lorsqu'ils entrent dans le viewport :

"use client";
 
import { useEffect, useRef, useState, ReactNode } from "react";
 
interface LazyChartProps {
  children: ReactNode;
  height?: number;
}
 
export default function LazyChart({ children, height = 400 }: LazyChartProps) {
  const ref = useRef<HTMLDivElement>(null);
  const [visible, setVisible] = useState(false);
 
  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setVisible(true);
          observer.disconnect();
        }
      },
      { rootMargin: "100px" }
    );
    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, []);
 
  return (
    <div ref={ref} style={{ minHeight: height }}>
      {visible ? children : null}
    </div>
  );
}

Enveloppez n'importe quel composant de graphique avec LazyChart pour différer le rendu jusqu'à ce qu'il entre dans le viewport.

Réduire la durée des animations

Pour les tableaux de bord avec plus de 4 graphiques, envisagez de réduire animationDuration à 400ms ou de désactiver complètement les animations avec isAnimationActive={false} pour accélérer le premier affichage.

Mémoïser les données des graphiques

Si vos données sont dérivées de réponses API, enveloppez les transformations dans useMemo pour éviter de recalculer à chaque rendu :

const chartData = useMemo(
  () => rawData.map((item) => ({ ...item, revenue: item.revenue / 100 })),
  [rawData]
);

Dépannage

Les graphiques ne se rendent pas côté serveur

Recharts utilise le DOM du navigateur et ne sera pas rendu pendant le rendu côté serveur. Marquez toujours les composants de graphiques avec "use client" et enveloppez-les dans ResponsiveContainer. Si vous voyez des erreurs d'hydratation, assurez-vous que le composant graphique est uniquement rendu côté client.

ResponsiveContainer a une hauteur de zéro

ResponsiveContainer hérite de ses dimensions de son parent. Si le parent n'a pas de hauteur explicite, le graphique s'effondre. Définissez toujours une prop height sur ResponsiveContainer ou assurez-vous que le conteneur parent a une hauteur définie.

L'infobulle scintille sur mobile

Sur les appareils tactiles, les infobulles peuvent scintiller car les événements tactiles se déclenchent différemment. Définissez allowEscapeViewBox sur le Tooltip pour l'empêcher d'être coupé aux limites du graphique :

<Tooltip allowEscapeViewBox={{ x: true, y: true }} />

Prochaines étapes

Maintenant que votre tableau de bord est fonctionnel, envisagez ces améliorations :

  • Sélecteur de plage de dates — permettre aux utilisateurs de filtrer les données par périodes personnalisées
  • Export en PDF — utilisez html-to-image et jsPDF pour exporter le tableau de bord
  • Mises à jour en temps réel — connectez-vous aux WebSockets ou Server-Sent Events pour des données en direct
  • Graphiques en profondeur — cliquez sur une barre pour voir les données détaillées
  • Barres empilées et groupées — comparer plusieurs catégories côte à côte
  • Composant Brush — ajouter un sélecteur de plage pour zoomer sur des périodes spécifiques

Recharts supporte tout cela nativement avec son modèle de composants composables.


Conclusion

Dans ce tutoriel, vous avez construit un tableau de bord complet d'analyse des ventes avec Recharts et Next.js App Router. Vous avez appris à :

  • Créer quatre types de graphiques différents — en barres, en lignes, en aires et circulaires
  • Construire des infobulles personnalisées pour une expérience utilisateur soignée
  • Rendre les graphiques responsives avec ResponsiveContainer
  • Récupérer des données dynamiques depuis des routes API Next.js
  • Supporter le mode sombre avec des couleurs de graphiques adaptatives
  • Optimiser les performances avec le chargement différé et la mémoïsation

Recharts est un choix puissant parce qu'il traite chaque élément de graphique comme un composant React composable. Vous le stylez, l'étendez et le testez de la même manière que n'importe quel autre composant de votre application. Associez-le à Tailwind CSS pour la mise en page et vous disposez d'une boîte à outils de tableau de bord qui passe du prototype à la production.


Vous voulez lire plus de tutoriels? Découvrez notre dernier tutoriel sur Stripe + Next.js — Guide Complet d'Intégration des Paiements 2026.

Discutez de votre projet avec nous

Nous sommes ici pour vous aider avec vos besoins en développement Web. Planifiez un appel pour discuter de votre projet et comment nous pouvons vous aider.

Trouvons les meilleures solutions pour vos besoins.

Articles connexes

Construire un Chatbot IA Local avec Ollama et Next.js : Guide Complet

Construisez un chatbot IA privé fonctionnant entièrement sur votre machine locale avec Ollama et Next.js. Ce tutoriel pratique couvre l'installation, le streaming des réponses, la sélection de modèles et le déploiement d'une interface de chat prête pour la production — le tout sans envoyer de données dans le cloud.

25 min read·