Search code examples
javascriptreactjsgraphstatebar-chart

How do I change the color of each bar in Recharts?


I have a bar graph on one of my React pages. It gets data from props that are passed on from another page. I have a bar graph showing three different pieces of data. One shows, "Correct", the other shows, "Incorrect", and the last shows, "Total". I would like to have the color of each bar be different. I've tried using the Cell feature but couldn't get it to work. I also tried changing the name of each piece of data but no luck. Unfortunately, there's not a lot of documentation out there for Recharts. Anybody have any ideas?

import React from 'react';
import {
    ResponsiveContainer, BarChart, Bar, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend,
} from 'recharts';

export default class GameChart extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            axes: [
                { primary: true, type: 'ordinal', position: 'left' },
                { position: 'bottom', type: 'linear', stacked: true }
            ],
            series: {
                type: 'bar'
            },
            chartData: [
                {
                    name: 'Correct',
                    total: 0,
                },
                {
                    name: 'Incorrect',
                    total: 0,
                },
                {
                    name: 'Total',
                    total: 0,
                },
            ],
            chartLayout: {
                title: 'Math Game Results',
                yaxis: {
                    showticklabels: false
                },
            }
        }
    }

    componentDidUpdate(prevProps) {
        if (prevProps.chartData.totalCounter !== this.state.chartData[2].total) {
            let tempState = this.state;
            tempState.chartData = [
                {
                    name: 'Correct',
                    total: this.props.chartData.correctCounter,
                },
                {
                    name: 'Incorrect',
                    total: this.props.chartData.incorrectCounter,
                },
                {
                    name: 'Total',
                    total: this.props.chartData.totalCounter,
                },
            ];
            this.setState(tempState);
        }
    }

    render () {
        return (
            <div>
                {
                    (this.state.chartData[2].total > 0) ?
                        (<ResponsiveContainer width="95%" height={225}>
                            <BarChart
                                data={this.state.chartData.slice()}
                                layout="vertical" barCategoryGap={5}
                                margin={{top: 5, right: 30, left: 20, bottom: 5,}}
                            >
                                <XAxis
                                    type="number"
                                    stroke="#000000"
                                />
                                <YAxis
                                    type="category"
                                    stroke="#000000"
                                    dataKey="name"
                                />
                                <Tooltip
                                    wrapperStyle={{ width: 100, backgroundColor: '#ccc' }}
                                    formatter={function(name) {return `${name}`}}
                                />
                                <Bar
                                    dataKey="total"
                                    fill="#00a0fc"
                                    stroke="#000000"
                                    strokeWidth={1}
                                />
                            </BarChart>
                        </ResponsiveContainer>
                        ):
                        (null)
                }
            </div>
        );
    }
}

Here's a picture of the current setup. As you can see, each bar has the same color. enter image description here


Solution

  • Ok, thanks to @c0m1t I got it working. All I had to do was make a list of colors above the state class!

    import React from 'react';
    import {
        BarChart, Bar, XAxis, Cell, YAxis, Tooltip, ResponsiveContainer,
    } from 'recharts';
    
    const barColors = ["#1f77b4", "#ff7f0e", "#2ca02c"]
    
    export default class Example extends React.Component {
        constructor(props) {
            super(props);
    
            this.state = {
                chartData: [
                    {
                        name: "Correct",
                        total: this.props.chartData.correctCounter
                    },
                    {
                        name: "Incorrect",
                        total: this.props.chartData.incorrectCounter
                    },
                    {
                        name: "Total",
                        total: this.props.chartData.totalCounter
                    }
                ]
            }
        }
    
        render() {
            return (
                <ResponsiveContainer width="95%" height={450}>
                    <BarChart
                        data={this.state.chartData.slice()}
                        margin={{ top: 20, right: 20, left: 20, bottom: 5, }}
                        data={this.state.chartData}
                    >
                    <XAxis
                        dataKey="name"
                        stroke="#000000"
                    />
                    <YAxis
                        stroke="#000000"
                    />
                    <Tooltip
                        wrapperStyle={{ width: 100, backgroundColor: '#ccc' }}
                        formatter={function(total) {return `${total}`}}
                    />
                    <Bar
                        dataKey="total"
                        fill="#00a0fc"
                        stroke="#000000"
                        strokeWidth={1}
                    >
                        {
                            this.state.chartData.map((entry, index) => (
                                <Cell key={`cell-${index}`} fill={barColors[index % 20]} />
                            ))
                        }
                    </Bar>
                    </BarChart>
                </ResponsiveContainer>
            );
        }
    }
    

    Now each bar has a different color. New bar chart with different color for each bar.