Improve plot performance with memoization

This commit is contained in:
Thomas Nordquist
2019-06-16 20:55:55 +02:00
parent c9aae4287c
commit 9fe5133ef1

View File

@@ -1,8 +1,7 @@
import * as React from 'react' import * as React from 'react'
import DateFormatter from '../helper/DateFormatter' import DateFormatter from '../helper/DateFormatter'
import { default as ReactResizeDetector } from 'react-resize-detector' import { default as ReactResizeDetector } from 'react-resize-detector'
import { Theme } from '@material-ui/core' import { Theme, withTheme } from '@material-ui/core'
import { withTheme } from '@material-ui/styles'
import 'react-vis/dist/style.css' import 'react-vis/dist/style.css'
const { XYPlot, LineMarkSeries, Hint, XAxis, YAxis, HorizontalGridLines } = require('react-vis') const { XYPlot, LineMarkSeries, Hint, XAxis, YAxis, HorizontalGridLines } = require('react-vis')
const abbreviate = require('number-abbreviate') const abbreviate = require('number-abbreviate')
@@ -12,61 +11,47 @@ interface Props {
theme: Theme theme: Theme
} }
interface Stats { export default withTheme((props: Props) => {
width: number const [width, setWidth] = React.useState(300)
value?: any const [tooltip, setTooltip] = React.useState({ value: undefined })
} const detectResize = React.useCallback(width => setWidth(width), [])
class PlotHistory extends React.Component<Props, Stats> { const hintFormatter = React.useCallback((point: any) => {
constructor(props: Props) {
super(props)
this.state = { width: 300 }
}
private resize = (width: number, height: number) => {
this.setState({ width: width - 12 })
}
private hintFormatter = (point: any) => {
return [ return [
{ title: <b>Time</b>, value: <DateFormatter date={new Date(point.x)} /> }, { title: <b>Time</b>, value: <DateFormatter date={new Date(point.x)} /> },
{ title: <b>Value</b>, value: point.y }, { title: <b>Value</b>, value: point.y },
] ]
} }, [])
private _forgetValue = () => { const hideTooltip = React.useCallback(() => {
this.setState({ setTooltip({ value: undefined })
value: undefined, }, [])
})
}
private _rememberValue = (value: any) => { const showTooltip = React.useCallback((value: any) => {
this.setState({ value }) setTooltip({ value })
} }, [])
public render() { const data = props.data
const data = this.props.data
return React.useMemo(() => {
return ( return (
<div style={{ height: '150px', overflow: 'hidden' }}> <div style={{ height: '150px', overflow: 'hidden' }}>
<XYPlot width={this.state.width} height={180}> <XYPlot width={width} height={180}>
<HorizontalGridLines /> <HorizontalGridLines />
<XAxis /> <XAxis />
<YAxis width={45} tickFormat={(num: number) => abbreviate(num)} /> <YAxis width={45} tickFormat={(num: number) => abbreviate(num)} />
<LineMarkSeries <LineMarkSeries
color={this.props.theme.palette.secondary.dark} color={props.theme.palette.secondary.dark}
onValueMouseOver={this._rememberValue} onValueMouseOver={showTooltip}
onValueMouseOut={this._forgetValue} onValueMouseOut={hideTooltip}
size={3} size={3}
data={data} data={data}
curve="curveMonotoneX" curve="curveMonotoneX"
/> />
{this.state.value ? <Hint format={this.hintFormatter} value={this.state.value} /> : null} {tooltip.value ? <Hint format={hintFormatter} value={tooltip.value} /> : null}
</XYPlot> </XYPlot>
<ReactResizeDetector handleWidth={true} onResize={this.resize} /> <ReactResizeDetector handleWidth={true} onResize={detectResize} />
</div> </div>
) )
} }, [width, data, tooltip])
} })
export default withTheme(PlotHistory)