Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 更新数据时,在React/D3中单击事件不更新_Reactjs_D3.js_Mouseevent - Fatal编程技术网

Reactjs 更新数据时,在React/D3中单击事件不更新

Reactjs 更新数据时,在React/D3中单击事件不更新,reactjs,d3.js,mouseevent,Reactjs,D3.js,Mouseevent,我有一个React组件,它呈现一个D3条形图,其中的条形图是可点击的。在更新父状态之前,它将按预期工作。条形图更新正确,但条形图上的单击事件仍绑定到以前的数据。我不确定这是否是我在React或D3或两者中做错的事情。感谢您的帮助 const DATA1 = [{"value":1}, {"value":1}] const DATA2 = [{"value":3}, {"value":3}, {"value":3}, {"value":2}, {"value":2}] const CLICK

我有一个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" 5
"data length on click" 2
我希望后者是:

"data length on render" 5
"data length on click" 5

这里的代码打开示例:

您可以尝试以下解决方案,将图表中的onclick事件更改为
this.chartRef.current.addEventListener(单击,()=>onclick(this.props.data.length);)
,将图表上的onclick props更改为
onclick={this.handleChartClick}
然后将句柄图表单击更改为
handleChartClick=(数据)=>{console.log('data length on click',data);}


我不清楚为什么要通过
handleChartClick
从图表组件传递数据,因为它已经在应用程序类状态下可用。您可以在
handleChartClick
中使用
this.state.data.length
您可以尝试以下解决方案,将图表中的onclick事件更改为
this.chartRef.current.addEventListener(单击,()=>onclick(this.props.data.length);
,将图表上的onclick道具更改为
onclick={this.handleChartClick}
然后将句柄图表单击更改为
handleChartClick=(数据)=>{console.log('data length on click',data);}


我不清楚为什么要通过
handleChartClick
从图表组件传递数据,因为它已经在应用程序类状态下可用。您可以在
handleChartClick中使用
this.state.data.length
,谢谢您的关注。我尝试了你的建议,但仍然得到同样的结果。新代码笔:如果只在图表的添加事件侦听器中添加数据,您可以将
()=>放在单击(this.props.data)
上吗。由于add event listener位于componentDidMount中,并且您第一次销毁了数据,因此后续onClick调用将引用该数据值。所以你需要参考这个.props.data来获得最新的值。好的,现在你指出它是有意义的。我更新了密码笔,它成功了!我数周来试图弄明白这一点的努力都是徒劳的。谢谢我发现除了enter选择之外,在更新选择中添加事件侦听器也很重要,否则鼠标事件回调处理程序没有最新版本的数据,即使它在中定义的呈现函数有。感谢您的关注。我尝试了你的建议,但仍然得到同样的结果。新代码笔:如果只在图表的添加事件侦听器中添加数据,您可以将
()=>放在单击(this.props.data)
上吗。由于add event listener位于componentDidMount中,并且您第一次销毁了数据,因此后续onClick调用将引用该数据值。所以你需要参考这个.props.data来获得最新的值。好的,现在你指出它是有意义的。我更新了密码笔,它成功了!我数周来试图弄明白这一点的努力都是徒劳的。谢谢我发现除了enter选择之外,在更新选择中添加事件侦听器非常重要,否则鼠标事件回调处理程序没有最新版本的数据,即使它在中定义的呈现函数有。
"data length on render" 5
"data length on click" 5