Search code examples
javascriptreactjsnestedbar-chartrecharts

Structuring data in Recharts


I have some data is nested, that looks a bit like this:

  let testData = [
    {
      animalType: 'Bird',
      data: [
        {
          animalName: 'Raven',
          animalLength: 120,
        },
        {
          animalName: 'Hawk',
          animalLength: 95,
        },
      ],
    },
    {
      animalType: 'Fish',
      data: [
        {
          animalName: 'Salmon',
          animalLength: 105,
        },
      ],
    },
    {
      animalType: 'Mammal',
      data: [
        {
          animalName: 'Dog',
          animalLength: 120,
        },
        {
          animalName: 'Cat',
          animalLength: 150,
        },
      ],
    },
  ];

I'm trying to create a Recharts Bar Chart using this data, but it's not working. Here's what I need the chart to look like:

enter image description here

So each bar should be the animalLength (and animalName), and should be grouped by animalType on the X Axis. I've been trying every iteration of this, but it seems like the double nested data doesn't allow it to work. There aren't many examples of this for Recharts so I couldn't get a good idea. This one is close, but the values for the X and Y axis are from within the same object.

Here's the BarChart code I'm using currently. Any help would be much appreciated.

 <BarChart
        width={1000}
        height={500}
        data={testData}
        margin={{ top: 40, right: 40, left: 0, bottom: 5 }}>
        <XAxis dataKey='animalType' />
        <YAxis dataKey='animalLength' />
        <CartesianGrid strokeDasharray='3 3' />
        {testData.forEach((agency) => {
          <Bar type='monotone' dataKey='animalName' />;
        })}
      </BarChart>

Solution

  • something like this will do the work if in each animal type you have 1 or 2 animal names... if you have more you will need to adjust

    import { BarChart, Bar, Cell, XAxis, YAxis, ResponsiveContainer } from 'recharts'
    
    let data = [
      {
        animalType: 'Bird',
        animal1Name: 'Raven',
        animal1Length: 120,
        animal1Color: 'red',
        animal2Name: 'Hawk',
        animal2Length: 95,
        animal2Color: 'red',
      },
      {
        animalType: 'Fish',
        animal1Name: 'Salmon',
        animal1Length: 105,
        animal1Color: 'blue',
      },
    
      {
        animalType: 'Mammal',
        animal1Name: 'Dog',
        animal1Length: 120,
        animal1Color: 'green',
        animal2Name: 'Cat',
        animal2Length: 150,
        animal2Color: 'green',
      },
    ]
    
    const App = () => {
      const renderBar = ({ x, y, width, height, animal2Name, fill }) => {
        return (
          <rect
            fill={fill}
            width={width}
            height={height}
            x={animal2Name ? x : x + 60}
            y={y}
            className="recharts-rectangle"
          ></rect>
        )
      }
      return (
        <div style={{ width: '1000px', height: '300px' }}>
          <ResponsiveContainer width="100%" height="100%">
            <BarChart
              width={500}
              height={300}
              data={data}
              margin={{
                top: 20,
                right: 30,
                left: 20,
                bottom: 5,
              }}
            >
              <XAxis dataKey="animalType" />
              <YAxis />
              <Bar dataKey="animal1Length" shape={renderBar}>
                {data.map((entry, index) => (
                  <Cell key={`cell-${index}`} fill={entry.animal1Color} />
                ))}
              </Bar>
              <Bar dataKey="animal2Length">
                {data.map((entry, index) => (
                  <Cell key={`cell-${index}`} fill={entry.animal2Color} />
                ))}
              </Bar>
            </BarChart>
          </ResponsiveContainer>
        </div>
      )
    }
    
    export default App