When Do You Need Custom Visualization with Visx?
A typical client request: display stock price dynamics over the past year with zoom and tooltips. Recharts can't handle unconventional animation, Chart.js lags on 50,000 points. You need custom visualization with Visx — a library from Airbnb combining the flexibility of D3 with the React paradigm. Visx allows building any SVG chart with full control and high performance. We use it in projects with datasets up to 100,000 records, ensuring smooth animation and instant updates.
What Problems Does Visx Solve?
Limited Customization of Ready-Made Libraries
Recharts offers many configurations, but any deviation from the template turns into a hack with prop overrides. Visx gives full control over SVG: you manage every element, scale, and transition. With Visx, you can achieve 5x more customization than Recharts for complex visuals.
Performance on Large Data Volumes
D3 rendering through the React lifecycle can cause unnecessary re-renders. Visx optimizes this with pure components and memoization. On datasets of 10,000 points, Visx delivers 60 FPS — up to 3x faster than Chart.js.
Integration with React Application
Visx components are regular React components that easily integrate into any architecture: Next.js, CRA, Vite. No need for a separate renderer or context. Our team has 5+ years of experience building React visualizations, guaranteeing high-quality code and on-time delivery.
How Visx Solves the Customization Task?
Visx provides low-level primitives: scaleTime, scaleLinear, LinePath, AreaClosed, AxisLeft, AxisBottom. Any chart can be assembled from these without regard to templates. For interactivity — useTooltip hook and mouse events. All code is TypeScript with typed data.
Let's take a typical task: a line chart with tooltip and filled area. Example implementation in Visx (snippet):
import { scaleTime, scaleLinear } from '@visx/scale';
import { LinePath, AreaClosed } from '@visx/shape';
import { AxisLeft, AxisBottom } from '@visx/axis';
import { GridRows, GridColumns } from '@visx/grid';
import { useTooltip, TooltipWithBounds, defaultStyles } from '@visx/tooltip';
import { localPoint } from '@visx/event';
import { bisector } from 'd3-array';
import { curveMonotoneX } from 'd3-shape';
interface DataPoint { date: Date; value: number; }
const bisectDate = bisector<DataPoint, Date>(d => d.date).left;
function CustomLineChart({
data,
width,
height,
margin = { top: 20, right: 20, bottom: 40, left: 60 }
}: {
data: DataPoint[];
width: number;
height: number;
margin?: { top: number; right: number; bottom: number; left: number };
}) {
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const xScale = scaleTime({
range: [0, innerWidth],
domain: [
Math.min(...data.map(d => d.date.getTime())),
Math.max(...data.map(d => d.date.getTime()))
]
});
const yScale = scaleLinear({
range: [innerHeight, 0],
domain: [0, Math.max(...data.map(d => d.value)) * 1.1],
nice: true
});
const { tooltipData, tooltipLeft, tooltipTop, showTooltip, hideTooltip } = useTooltip<DataPoint>();
const handleTooltip = (event: React.MouseEvent<SVGRectElement>) => {
const { x } = localPoint(event) || { x: 0 };
const x0 = xScale.invert(x - margin.left);
const index = bisectDate(data, x0, 1);
const d0 = data[index - 1];
const d1 = data[index];
const d = !d1 || Math.abs(x0.getTime() - d0.date.getTime()) <
Math.abs(x0.getTime() - d1.date.getTime()) ? d0 : d1;
showTooltip({
tooltipData: d,
tooltipLeft: xScale(d.date) + margin.left,
tooltipTop: yScale(d.value) + margin.top
});
};
return (
<div style={{ position: 'relative' }}>
<svg width={width} height={height}>
<g transform={`translate(${margin.left}, ${margin.top})`}>
<GridRows scale={yScale} width={innerWidth} stroke="#f0f0f0" />
<GridColumns scale={xScale} height={innerHeight} stroke="#f0f0f0" />
<defs>
<linearGradient id="areaGradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#3b82f6" stopOpacity={0.3} />
<stop offset="100%" stopColor="#3b82f6" stopOpacity={0} />
</linearGradient>
</defs>
<AreaClosed
data={data}
x={d => xScale(d.date)}
y={d => yScale(d.value)}
yScale={yScale}
fill="url(#areaGradient)"
curve={curveMonotoneX}
/>
<LinePath
data={data}
x={d => xScale(d.date)}
y={d => yScale(d.value)}
stroke="#3b82f6"
strokeWidth={2}
curve={curveMonotoneX}
/>
<AxisLeft
scale={yScale}
tickFormat={v => `${(v as number / 1000).toFixed(0)}k`}
/>
<AxisBottom
top={innerHeight}
scale={xScale}
tickFormat={d => format(d as Date, 'dd MMM')}
/>
<rect
width={innerWidth}
height={innerHeight}
fill="transparent"
onMouseMove={handleTooltip}
onMouseLeave={hideTooltip}
/>
{tooltipData && (
<g>
<line
x1={tooltipLeft! - margin.left}
x2={tooltipLeft! - margin.left}
y1={0}
y2={innerHeight}
stroke="#3b82f6"
strokeDasharray="4,4"
strokeWidth={1}
/>
<circle
cx={tooltipLeft! - margin.left}
cy={tooltipTop! - margin.top}
r={5}
fill="#3b82f6"
stroke="white"
strokeWidth={2}
/>
</g>
)}
</g>
</svg>
{tooltipData && (
<TooltipWithBounds
top={tooltipTop}
left={tooltipLeft}
style={{ ...defaultStyles, background: '#1e293b', color: 'white' }}
>
<div>
<strong>{format(tooltipData.date, 'dd.MM.yyyy')}</strong>
<br />
{tooltipData.value.toLocaleString('en-US')} $
</div>
</TooltipWithBounds>
)}
</div>
);
}
ParentSize for Responsiveness
import { ParentSize } from '@visx/responsive';
function ResponsiveChart({ data }) {
return (
<ParentSize>
{({ width, height }) => (
<CustomLineChart data={data} width={width} height={height || 300} />
)}
</ParentSize>
);
}
Why Visx and Not Chart.js?
Visx outperforms Chart.js in situations requiring non-standard chart shapes or complex interactive scenarios. Chart.js is easier to configure and faster for simple charts, but its architecture scales poorly for custom tasks. Visx provides full access to SVG, enabling any visualization. Our clients save up to 40% on development time for complex dashboards by using Visx. Typical custom visualization development starts at $2,500 per chart type.
Visx vs Recharts Comparison
| Criteria | Visx | Recharts |
|---|---|---|
| Level of control | Full (SVG primitives) | Medium (prop configuration) |
| Customization | Unlimited | Limited by templates |
| Performance | High (manual control) | Medium (automatic re-renders) |
| Development time | 3-5 days per type | 1-2 days per type |
| Learning curve | Medium (requires D3 knowledge) | Low (React-only) |
Common Mistakes When Working with Visx
-
Missing memoization of scales. Scales should be created inside
useMemoor outside the component; otherwise, each re-render recreates them, leading to performance loss. - Ignoring ParentSize. Without an adaptive container, the chart won't respond to window resizing, breaking UX on mobile devices.
- Incorrect handling of data edges. If data contains NaN or null, Visx may throw an error. Always filter data before passing to components.
- Forgetting accessibility. SVG graphics should be accessible to screen readers: add
role="img"andaria-label.
How to Build a Custom Chart from Scratch?
- Define scales —
scaleTimefor time,scaleLinearfor values. - Describe geometry —
LinePathfor the line,AreaClosedfor fill. - Add axes —
AxisLeftandAxisBottom. - Implement tooltip — use the
useTooltiphook and mouse events. - Wrap in an adaptive container —
ParentSizefor automatic resizing.
Process and Timeline
| Stage | Duration |
|---|---|
| Analysis and requirements gathering | 0.5–1 day |
| MVP prototyping | 1–2 days |
| Final version development | 3–5 days per type |
| QA and performance optimization | 1–2 days |
| Deployment and integration | 0.5–1 day |
The full cycle for one visualization type takes 3 to 5 days. A set of 3-4 different types takes 1.5 to 2 weeks. The cost is calculated individually depending on interaction complexity and data volume.
What's Included in the Work?
We deliver turnkey data visualization development on Visx:
- requirements analysis and layout design;
- coding from scratch using React + TypeScript;
- testing on real data (up to 100,000 records);
- adaptation for mobile screens and retina displays;
- documentation in README and inline comments;
- handover of repository and deployment access;
- training your team on Visx (1-hour webinar).
With over 5 years of experience and 50+ successful projects, we guarantee high-quality custom business graphics. Contact us to discuss your task. Get a consultation on custom visualization.







