Skip to content

Comments

Prevent tickFormat from receiving incorrect intermediate values on initial render#1979

Open
wildseansy wants to merge 1 commit intoairbnb:masterfrom
wildseansy:master
Open

Prevent tickFormat from receiving incorrect intermediate values on initial render#1979
wildseansy wants to merge 1 commit intoairbnb:masterfrom
wildseansy:master

Conversation

@wildseansy
Copy link

🐛 Bug Fix: Prevent tickFormat from receiving incorrect intermediate values on initial render

Problem

After updating @visx/xychart to version 4.0.1-alpha.0, the tickFormat function receives unexpected intermediate values (0 → 1 range) instead of the actual x values from the dataset on the initial render (see #1975)

Example:

<AnimatedAxis
  orientation="bottom"
  tickFormat={(value: string) => {
    console.log(value); // Logs: 0, 0.1, 0.2, ..., 1, then "2020-01-01", "2020-01-02", "2020-01-03"
    return value;
  }}
/>

This breaks formatting logic when users expect only their domain values.

Root Cause

The issue stems from a render timing problem:

  1. Initial render: XYChart and its children mount
  2. Data registration deferred: Series components (LineSeries, etc.) register data via useEffect, which runs after the initial render
  3. Empty data → undefined scale: useScales() returns undefined when no data is registered yet
  4. Fallback scale provided: DataProvider provides scaleLinear() as a fallback (with default domain [0, 1])
  5. Axis renders prematurely: BaseAxis checks scale ? which is truthy, so it renders
  6. Wrong ticks generated: getTicks() on a linear scale with domain [0, 1] generates ticks: 0, 0.1, 0.2, ..., 1
  7. tickFormat receives wrong values: These intermediate values are passed to the user's tickFormat function

Solution

Added a check in BaseAxis to only render when data has been registered in the dataRegistry:

// Don't render axis until data is registered, otherwise the fallback scaleLinear()
// with domain [0,1] will cause tickFormat to receive incorrect intermediate values.
const hasRegisteredData = dataRegistry && dataRegistry.keys().length > 0;

return scale && hasRegisteredData ? (
  <AxisComponent ... />
) : null;

Changes

  • packages/visx-xychart/src/components/axis/BaseAxis.tsx
    • Added dataRegistry to the destructured context values
    • Added hasRegisteredData check before rendering
    • Updated render condition from scale ? to scale && hasRegisteredData ?

Testing

After this fix, tickFormat will only receive the actual domain values:

2020-01-01
2020-01-02
2020-01-03

@wildseansy wildseansy changed the title Fix for https://github.com/airbnb/visx/issues/1975 Prevent tickFormat from receiving incorrect intermediate values on initial render Jan 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant