recharts / recharts

Redefined chart library built with React and D3
http://recharts.org
MIT License
24.08k stars 1.71k forks source link

Axis scale="band" no longer works as of Recharts 2.x.x #2742

Open danatemple opened 2 years ago

danatemple commented 2 years ago

Reproduction link

Edit on CodeSandbox

Steps to reproduce

Run the code sandbox, which is closely based on the recharts bars example. It also fails on 2.0.x.

What is expected?

I expect that the X axis ticks are placed "around" the bars in the same way that scale="band" used to do in Recharts 1.8.5. See this 1.8.5 example: https://codesandbox.io/s/histogram-recharts-1-8-5-wvvqu

What is actually happening?

scale="band" has no effect. You can delete it from the without the graph changing at all.

Environment Info
Recharts v2.1.6
React 17.0.1
System Codesandbox on Chrome, Windows 10
Browser Chrome 96

I use scale="band" to display histograms, where the axis ticks need to be at the points between the bars, because they are showing the start and end of the histogram bin.

There is still an issue with the last tick, but I work around this by adding a second axis with just that tick.

semoal commented 2 years ago

I think it changed internally from the d3-scale library of how it works.

You could give it a try to this and see if has effect:

import { scaleBand } from "d3-scale";
const scale = scaleBand().domain(["a"]).range([0,100]);
...
      <XAxis dataKey="name" scale={scale} padding={{ left: 10, right: 10 }} />
danatemple commented 2 years ago

@semoal thanks, but I just tried in CodeSandbox, didn't seem to have any effect.

semoal commented 2 years ago

Cool, looks like a regression we'll look into it as soon as possible. I want before the end of this year to decide a roadmap and start giving some fresh air to the library.

danatemple commented 2 years ago

@semoal just wondering what the expectation is here for a fix?

It is kind of blocking us, as we can't upgrade React beyond 16.4 (we hit a very obscure crash with Recharts 1.x) until we upgrade Recharts to 2.x.

Would be happy to pay for someone to work on this, as I appreciate there are many demands on time...

bsplosion commented 2 years ago

This is also affecting our implementation. I tried to hunt through the source for a potential PR but wasn't familiar enough with the methods used to contribute on this one. Seems like whatever happened during conversion of util/CartesianUtils from JS to TS broke, if I were to guess. I'll keep looking around and seeing if there's anything that leaps out.

LouisMlr commented 2 years ago

Hello, are there any updates/workaround? I am also annoyed by this bug for displaying histograms in my react application.

chenasraf commented 2 years ago

Any update on this?

danatemple commented 2 years ago

@chenasraf @semoal Yes, I employed someone to fix this, and just heard this morning that the fix is done. A PR should be coming v.soon. Watch this space!

danatemple commented 2 years ago

Note to anyone using patch-package to apply this fix in the meantime.

You need to apply it to the es6/utils/ChartUtils.js copy under node_modules, and the one under src/

To avoid a bug in "npm ci" you also need to add the "name" property to your package.json.

npm bug ref

danatemple commented 2 years ago

@semoal and anyone else affected. With the PR #2794 there is still a small remaining issue, with a 2 pixel horizontal offset.

This can be worked around by replacing the final '0' with a '2':

- let offset = (isGrid || isAll) && type === 'category' && scale.bandwidth ? scale.bandwidth() / 2 : 0;
+ let offset = (isGrid || isAll) && type === 'category' && scale.bandwidth ? scale.bandwidth() / 2 : 2;

But not being familiar with the code we are reluctant to post this as a fix without understanding why.

uazure commented 2 years ago

Though I see a fix and that it's actually has some effect. It still has issues with 'bands' scale type. There's a line drawed on cartesian grid at the beginning of the canvas.. that does not relate to the scale itself. And I don't know how to get rid of it. Also, tooltip hover looks quite strange. Probably there should be a better solution to support band scale type.

https://codesandbox.io/s/histogram-recharts-2-1-15-forked-e0g1sb?file=/src/App.tsx

https://user-images.githubusercontent.com/456298/197556504-22b25251-1150-4df8-aba2-fd76a7403f1c.mp4

klaidaslekavicius commented 1 year ago

@uazure I'm observing the exact same issue. Does anyone have clue how it would be possible to overcome this problem with Tooltip being offset from the bars themselves? 👆

blerner commented 1 year ago

I have a workaround I just found, with v2.5.0 that seems to work for my case, based on the storybook example with multiple X axes -- I create my data as a list of records

{
  count: number,
  range: `${bin.x0}-${bin.x1}`,
  x0: bin.x0,
  x1: bin.x1
}

and then I can render the bar graph with two x-axes:

              <BarChart data={buckets}>
                <XAxis dataKey="range" hide />
                <XAxis dataKey="x0" scale="band" xAxisId="values" />
                <YAxis />
                <Tooltip />
                <Bar dataKey="count" fill={somePrettyColor()} />
              </BarChart>

The axis based on "range" sets the rendering of the bars in the bar-chart, but that axis is hidden; and then the axis based on "x0" renders ticks where I want them.

Hope this helps someone else!

uazure commented 3 months ago

I have a workaround I just found, with v2.5.0 that seems to work for my case, based on the storybook example with multiple X axes -- I create my data as a list of records

{
  count: number,
  range: `${bin.x0}-${bin.x1}`,
  x0: bin.x0,
  x1: bin.x1
}

and then I can render the bar graph with two x-axes:

              <BarChart data={buckets}>
                <XAxis dataKey="range" hide />
                <XAxis dataKey="x0" scale="band" xAxisId="values" />
                <YAxis />
                <Tooltip />
                <Bar dataKey="count" fill={somePrettyColor()} />
              </BarChart>

The axis based on "range" sets the rendering of the bars in the bar-chart, but that axis is hidden; and then the axis based on "x0" renders ticks where I want them.

Hope this helps someone else!

you saved my day man! thanks! Helped me with handling clicks on band chart. Though I had to make custom renderer for cartesian grid to imitate bands