У меня есть компонент React, который отображает столбчатую диаграмму D3, где столбцы можно нажимать. Он работает, как и ожидалось, пока родительское состояние не будет обновлено. Стержни обновляются правильно, но события щелчков на панелях все еще привязаны к предыдущим данным Я не уверен, что я что-то не так делаю в React, D3 или обоих. Любая помощь приветствуется.
const DATA1 = [{"value":1}, {"value":1}]
const DATA2 = [{"value":3}, {"value":3}, {"value":3}, {"value":2}, {"value":2}]
const CLICK = 'chartClick'
function handleClick(data, i, els) {
const element = els[i]
const event = new Event(CLICK, {bubbles: true, detail: data})
return element.dispatchEvent(event)
}
class D3Chart {
constructor(selector) {
this.svg = d3.select(selector).append('svg')
}
draw(data) {
const xScale = d3.scaleLinear()
.domain([0, d3.max(data.map(i => i.value))])
.range([0, 500])
const barGroups = this.svg.selectAll('.barGroup').data(data)
const barGroupsEnter = barGroups.enter().append('g')
.attr('class', 'barGroup')
.attr('transform', (d, i) => {
const y = (i * 25)
return `translate(0, ${y})`
})
barGroupsEnter.append('rect')
.attr('class', 'bar')
.attr('height', 20)
.attr('width', d => xScale(d.value))
.on('click', handleClick)
barGroups.exit().remove()
}
}
class Chart extends React.Component {
chartRef = React.createRef()
componentDidMount() {
const {data, onClick} = this.props
this.chartRef.current.addEventListener(CLICK, onClick)
this.chart = new D3Chart(this.chartRef.current)
this.chart.draw(data)
}
shouldComponentUpdate(nextProps) {
const {data} = this.props
return !_.isEqual(data, nextProps.data)
}
componentDidUpdate() {
const {data} = this.props
this.chart.draw(data)
}
render() {
return <div ref={this.chartRef}></div>
}
}
class App extends React.Component {
state = {data: DATA1}
handleButtonClick = () => this.setState({data: DATA2})
handleChartClick = (data, event) => console.log('data length on click', data.length)
render() {
const {data} = this.state
console.log('data length on render', data.length)
return (
<React.Fragment>
<button onClick={this.handleButtonClick}>Update Data</button>
<Chart data={data} onClick={(event) => this.handleChartClick(data, event)} />
</React.Fragment>
)
}
}
ReactDOM.render(<App />, document.querySelector('.root'))
Вывод при первом рендере / клике:
"data length on render" 2
"data length on click" 2
Выход после обновления данных:
"data length on render" 5
"data length on click" 2
Я ожидаю, что последний будет:
"data length on render" 5
"data length on click" 5
Пример Codepen здесь: https://codepen.io/bohmanart/pen/QPQJdX