Skip to content

Dynamically added series lose event bindings in VictorySharedEvents due to stale props.children in shouldComponentUpdate #3082

@dharmeshkota

Description

@dharmeshkota

Is there an existing issue for this?

  • I have searched the existing issues

Code of Conduct

  • I agree to follow this project's Code of Conduct

Victory version

37.3.6

Code Sandbox link

No response

Bug report

There is a bug in victory-shared-events.js where conditionally adding a new series to a <VictoryChart> (e.g., toggling visibility of a <VictoryBar>) results in the newly added series silently losing all event bindings (like hovers and tooltips).

The Root Cause:
When a new series is added, React passes new children to <VictoryChart>, triggering an update in <VictorySharedEvents>.
Inside shouldComponentUpdate(nextProps), the component recalculates base properties via this.baseProps = this.getBaseProps(nextProps);.

However, inside getBaseProps(props), the function incorrectly reads from this.props.children instead of the newly passed props.children:

JavaScript
getBaseProps(props) {
  const { container } = props; 
  // THE BUG: Reads old children from this.props, ignoring the nextProps passed in
  const children = React.Children.toArray(this.props.children); 
  const childBaseProps = this.getBasePropsFromChildren(children);
  // ...
}
The Cascading Failure:

Because this.baseProps is generated using the old children, it creates a stale snapshot that is missing the newly added series.

In the render() method, the component passes the new props.children alongside the stale this.baseProps into getNewChildren(props, baseProps).

Inside alterChildren, Victory attempts to map the newly rendered React components to its internal childNames array (derived from baseProps).

Because the childNames array is too short, the slice method shifts the indices. The newly added series at the end of the array accidentally absorbs the "parent" string as its designated name.

In the event-binding block, the code explicitly checks childNames[index] !== "parent". Because the new series was mistakenly named "parent", it bypasses the sharedEvents injection entirely and is returned as a plain React element.

The Fix:
Change this.props.children to props.children inside getBaseProps (or wherever children are accessed during the shouldComponentUpdate flow) so it correctly utilizes nextProps.

Steps to reproduce

Steps to reproduce

1. Create a <VictoryChart> with a VictoryGroup containing 3 <VictoryBar> components.
2. Use state to conditionally render a 4th <VictoryBar> at the end of the group.
3. Toggle the state to mount the 4th <VictoryBar>.
4. Attempt to trigger an onMouseOver event (e.g., a shared tooltip) on the newly added 4th bar.

Expected behavior

The newly added series should correctly register in Victory's internal event system and trigger hover events, mutations, and tooltips just like the initial series.

Actual behavior

The newly added series renders visually on the screen but silently fails to trigger any events. It is entirely orphaned from the VictorySharedEvents system because it bypassed the event-binding logic.

Environment

- Device: Desktop
- OS: macOS
- Node: 25.3.0
- pnpm: 10.33.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: Bug 🐛Oh no! A bug or unintentional behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions