Skip to content
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

React state change doesn't always trigger a chart redraw #2221

Open
mattbadley opened this issue May 6, 2022 · 2 comments
Open

React state change doesn't always trigger a chart redraw #2221

mattbadley opened this issue May 6, 2022 · 2 comments
Labels
Issue: Accepted The submitted issue has been confirmed by the Victory core team Type: Enhancement ✏️ An enhancement or feature proposal that will be addressed after the next release

Comments

@mattbadley
Copy link

I am trying to create a line chart where hovering over an activate data point will also show a vertical line at that point - as per gif below.

2022-05-06 15 40 50

The intention is for the green line to only appear when a point on the chart is active, meaning it should hide once the user moves the mouse away from the chart and no scatter point is selected.

I have some code that achieves this outcome but it uses react state, and changes to the state don't always re-render the chart. The code checks if there is an active object, and only renders the line if there is. However due to the state being one step behind (usually), the line doesn't disappear when you roll off the chart.

Is there a better approach to what I'm trying to achieve here or a way I can force the chart to update when active becomes null?

const [active, setActive] = useState<any>(null)

  const onActivated = (points: any[], props: any) => {
    if (points?.length && props?.mousePosition?.x) {
      setActive({ point: points[0], mouseX: props.mousePosition.x })
    }
  }

  const onDeactivated = (points: any[], props: any) => {
    if (!points?.[0]?.eventKey) {
      setActive(null)
    }
  }

  const activeDataPointX = (): number => {
    const startX = 0
    if (active?.point?.eventKey) {
      return startX + (active.point.eventKey / (chartData.length - 1)) * chartWidth
    }
    return startX
  }

  const chartWidth = 400
  const chartHeight = 400

  const chartData = [
    { x: 1, y: 2 },
    { x: 2, y: 3 },
    { x: 3, y: 5 },
    { x: 4, y: 4 },
    { x: 5, y: 7 },
  ]

  return (
    <VictoryChart
      theme={VictoryTheme.grayscale}
      width={chartWidth}
      height={chartHeight}
      containerComponent={
        <VictoryVoronoiContainer
          voronoiDimension="x"
          labels={({ datum }) => `y: ${datum.y}`}
          labelComponent={<VictoryTooltip constrainToVisibleArea />}
          onActivated={(points, props) => onActivated(points, props)}
          onDeactivated={(points, props) => onDeactivated(points, props)}
        />
      }
    >
      {active?.point?.eventKey && (
        <line
          x1={activeDataPointX()}
          y1="0"
          x2={activeDataPointX()}
          y2={chartHeight}
          stroke={'#00ff00'}
        />
      )}
      <VictoryLine
        style={{
          data: { stroke: '#c43a31' },
          parent: { border: '1px solid #ccc' },
        }}
        data={chartData}
      />
      <VictoryScatter data={chartData} size={({ active }) => (active ? 10 : 5)} />
    </VictoryChart>
)}

Another issue here is that when using voronoiDimension="x" it makes the tooltip move with the mouse on the y-axis. Is there a way to prevent that? It looks like the only way is to remove §voronoiDimension="x", but then you no longer get the desired mouse/point detection.

As well as this issue, there seems to be a bug when rolling over the first scatter data point -

Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'name')

Call Stack
eval
../../node_modules/victory-core/es/victory-util/helpers.js (290:0)
Array.reduce
<anonymous>
traverseChildren
../../node_modules/victory-core/es/victory-util/helpers.js (288:0)
Module.reduceChildren
../../node_modules/victory-core/es/victory-util/helpers.js (322:0)
getStringsFromCategories
../../node_modules/victory-core/es/victory-util/wrapper.js (372:9)
getCategoryAndAxisStringsFromChildren
../../node_modules/victory-core/es/victory-util/wrapper.js (419:0)
Module.getStringsFromChildren
../../node_modules/victory-core/es/victory-util/wrapper.js (424:0)
getCalculatedProps
../../node_modules/victory-chart/es/helper-methods.js (103:19)
eval
../../node_modules/victory-chart/es/victory-chart.js (48:29)
updateMemo
../../node_modules/react-dom/cjs/react-dom.development.js (15867:0)
Object.useMemo
../../node_modules/react-dom/cjs/react-dom.development.js (16413:0)
Object.useMemo
../../node_modules/react/cjs/react.development.js (1532:0)
VictoryChart
../../node_modules/victory-chart/es/victory-chart.js (47:24)

Any help would be appreciated.

Thanks,

Matt

@mordechaim
Copy link

mordechaim commented Jul 27, 2022

For your latter issue with reading name from undefined, try changing the conditional render to:

{active?.point?.eventKey != null && (
        <line
          x1={activeDataPointX()}
          y1="0"
          x2={activeDataPointX()}
          y2={chartHeight}
          stroke={'#00ff00'}
        />
)}

Victory children must either be components or false. A falsey conditional such as 0 or empty string will blow up.

@embooglement
Copy link

I'm running into the same issue with tooltips not properly deactivating when mousing out of a chart:
Screen Shot 2023-01-26 at 4 14 34 PM

I got this by moving my cursor around the chart a lot. The chart itself is basically the same as Matt's above, a set of VictoryLines and VictoryScatters, wrapped in a VictoryVoronoiContainer.

Is there a workaround for this at all? I'd love a simple way to force all data points to deactivate, but it's not obvious if that's possible to do using mutations from Victory's event system.

@carbonrobot carbonrobot added Type: Enhancement ✏️ An enhancement or feature proposal that will be addressed after the next release Issue: Accepted The submitted issue has been confirmed by the Victory core team labels Feb 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue: Accepted The submitted issue has been confirmed by the Victory core team Type: Enhancement ✏️ An enhancement or feature proposal that will be addressed after the next release
Projects
None yet
Development

No branches or pull requests

4 participants