-
Notifications
You must be signed in to change notification settings - Fork 730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performant way to update scales? #608
Comments
Figured out a way that works. In d3.select(this.lineRef.current)
.attr('d', line) To this: d3.select(this.lineRef.current)
.datum(data)
.attr('d', line) Would love any suggestions on how to further simplify/react-ify this code if possible. Will close since I found something that works for me. |
It would be nice to be able to pull the existing d3 e.g. Instead of this: const line = d3.line()
.x(d => this.xScale(d.index))
.y(d => this.yScale(d.price))
d3.select(this.lineRef.current)
.attr('d', line) It would be nice to be able to do something like this: d3.select(this.lineRef.current)
.attr('d', this.outerRef.d3line)
// ...
<LinePath
ref={this.outerRef}
innerRef={this.lineRef}
/> Because the attached d3 line isn't really changing, it's just being re-applied while the scale that its |
Hi @cilphex 👋 thanks for checking out I'm curious if a "pure function MyLine({ width, height, data }) {
const [maxDays, setMaxDays] = useState(/** initialMaxDays */);
// recompute scales only if chart dims or data change
const yScale = useMemo(() => /** compute yScale */, [data, height]);
const xScale = useMemo(() => scalePower({
range: [0, width],
domain: [0, maxDays],
exponent: 0.5
}), [data, width]);
useEffect(() => {
// update the x domain when maxDays changes
xScale.domain([0, maxDays])
}, [maxDays]);
return (
<>
<input {...} onChange={() => setMaxDays(...)} />
<svg {...}>
<LinePath>
{({ path }) => (
// get an empty default path, override x and y
path.x(d => xScale(d.index));
path.y(d => yScale(d.price));
return (
<path d={path(data) || ''} {...} />
);
)}
</LinePath>
</svg>
</>
);
} |
I would also note that for animations in typically re-creating objects (like scales) is not the expensive part, it's |
@williaster Just saw your comments, I'll give them a try soon. My React knowledge might be out of date/inadequate, as I'm not familiar with
^ Yep, that's what I'm discovering! Any way I can update vx components in the "react way" without using |
@williaster I think Also curious how you would apply this solution to the |
I'm trying to make a chart where the scale's domain is adjustable through a slider (input[type="range"]) beneath the chart. (Like this, for example.)
The problem that I am running into is that using setState is not performant, as I would like updates to happen every few ms as the slider is dragged, and not just about once per second.
With setState, I'd do something like this:
This example ^ is slow and laggy. As the user drags the range slider, the chart scale updates, but it is very choppy.
The more performant alternative is to use the
innerRef
property on the line path so I can access it directly, and then use native d3 logic to set the scale. But I'm having trouble figuring out how to do this.Any tips or is there a different preferred way to do this?
The text was updated successfully, but these errors were encountered: