Hi,
I am seeing poor performance in my bars chart with ~300 data points, and am trying to follow the suggestion outlined in this post. However, I can't figure out a way to stop default styles from being applied inline to my data <path/>s.
Is there a way to null out default styles being applied? Alternatively, if anyone knows of other more recent tricks to optimize performance, that would be very appreciated.
(Additional information -- part of my issue seems to be associated with a callback being done on hover, which calls setState in the parent component. My chart component extends PureComponent so I am not sure why this is degrading performance. Regardless, even with no event handlers, panning performance is jagged for me.)
@timhwang21 Victory is built to use inline styles rather than css. If you want to alter that, you will need to define your own custom dataComponent for whatever you are rendering. You can read about how to create custom components here: https://formidable.com/open-source/victory/guides/custom-components
If you're rendering a bar chart with 300 data points, you might consider using a VictoryArea component with interpolation="step" instead. That should help performance a lot since you would then be rendering just one element instead of 300.
I'm not sure what you mean when you say that your chart component extends PureComponent... Victory components do not extend PureComponent as we are often dealing with arrays and nested objects, so we can't rely on a shallow equality check. All rendered components (_i.e._ Bar, VictoryLabel etc. implement custom shouldComponentUpdate logic instead.) That was all implemented after the issue you reference. What version of Victory are you using?
@boygirl thanks for the response!
For dataComponent I am passing in the primitive <Bar/> with a classname. Would I have to make my own version of <Bar/> that is identical, but without the inline styles?
I'll see if VictoryArea works for our use case, but ultimately that is up to our UX team -- I'm just a code monkey ;)
Regarding PureComponent, I should have been more detailed -- my setup looks like this:
// Components
// MyChartContainer.js - simple wrapper component that stores the data point user's mouse is over in state
// MyChart - component extending PureComponent that renders a VictoryChart. On the VictoryBar there is an event handler that runs a callback from MyChartContainer on mouseover, which sets state in MyChartContainer
// SomeSpan // component unrelated to the chart that uses MyChartContainer's state to display inf about the hovered data point
<MyChartContainer>
<MyChart/> // MyChartContainer state not passed here so it shouldn't rerender even when MyChartContainer rerenders due to state change
<SomeSpan/>
</MyChartContainer>
If my setup is right, the fact that hovering over bars is setting state in <MyChartContainer/> should be irrelevant to the chart, since it's not rendering. However, removing the setState() callback seemed to improve performance -- but does not improve to the point where panning is smooth.
@timhwang21 sorry for the slow reply. The safest thing to do would be to duplicate all the Bar code. The easier thing to do, would be to actually _extend_ Bar, as we are doing in victory-native https://github.com/FormidableLabs/victory-native/blob/master/lib/components/victory-primitives/bar.js. If you go that route, you'll need to be aware of internal code changes, but if you stick with just overriding the renderBar method that is also overridden by victory-native you can be confident that changes to that function signature will be versioned as breaking changes (since they would break victory-native).
By the way, I found a way to override default inline styles for VictoryLabel. Just pass it the following styles:
{
fill: null,
fontSize: null,
fontFamily: null,
stroke: null }
This way you can use your own styles in a CSS selector without having to resort to !important. It would be much easier if VictoryCharts provided its default styles using classes instead of inline styles, but I understand that that approach comes with other headaches, such as the question how to include the stylesheet.
Most helpful comment
By the way, I found a way to override default inline styles for VictoryLabel. Just pass it the following styles:
This way you can use your own styles in a CSS selector without having to resort to !important. It would be much easier if VictoryCharts provided its default styles using classes instead of inline styles, but I understand that that approach comes with other headaches, such as the question how to include the stylesheet.