繁体   English   中英

使用 d3 更新 dom ref 并做出反应

[英]update dom ref using d3 and react

我有一个带有d3函数的functional component ,它在安装时将p附加到ref

我正在尝试使用useState挂钩更改附加段落的文本内容

点击按钮<button type="button" onClick={(e)=> setData("bar")}>change data</button>触发重新渲染,而不是更改p标签的文本,一个新的d3 函数的版本被创建 --> 追加一个新的p

阅读参考更改时如何重新渲染建议使用useCallback钩子,我不确定如何实现

如何在不创建新段落的情况下实现段落的重新渲染?

import {useEffect, useState, useRef} from 'react'

import * as d3 from 'd3'

function DomReference() {

  const domRef = useRef()

  const [data, setData] = useState("foo")

  useEffect(()=>{


    d3.select(domRef.current)
      .append('p')
      .text(data)
    
    // re-render --> creates a new function 
    
  }, [data])


  return (
    <div ref={domRef}>
      <button type="button" onClick={(e)=> setData("bar")}>change data</button>
      
    </div>
  )
}

export default DomReference

d3 append 函数在执行时总是会创建一个新元素。

要始终只有一个段落并且只更新其值,您可以使用d3.join

代替:

  d3.select(domRef.current)
      .append('p')
      .text(data)

你可以使用:

  d3.select(domRef.current).selectAll('p')
    .data([data])
    .join('p')
    .text(d => d)

逐行解释:

  • d3.select(domRef.current).selectAll('p') : 选择domRef.current所有<p>元素
  • .data([data]) :将<p>元素绑定到数据数组。 绑定时,数组中的每个项目都有自己的<p>
  • .join('p')join将创建一个选择,删除所有没有关联数据的<p> ,并更新有数据的那些。 这将为您留下一个<p> ,因为之前的.data()调用在数组中只有一个元素
  • .text(d => d) :此回调是您访问与<p>关联的数据的方式。

作为补充:

如果您不想删除所有其他<p> ,您可以使用一个类来缩小您的选择范围:

  d3.select(domRef.current).selectAll('p.myOddParagraphs')
    .data([1, 3, 5])
    .join('p')
    .classed('myOddParagraphs', true)
    .text(d => d)

   d3.select(domRef.current).selectAll('p.myEvenParagraphs')
    .data([2, 4, 6])
    .join('p')
    .classed('myEvenParagraphs', true)
    .text(d => d)

上面的代码将导致 6 段:三个绑定到[1, 3, 5]数组,其他三个绑定到[2, 4, 6]

原则上,你不应该在使用 React 时尝试使用 D3 来改变 DOM,因为 React 不会意识到这样的变化。 这通常会导致很难发现和调试的非常讨厌的错误。 如果你发现自己在 React 中使用了attrappend ,那你就错了;)

这并不是说你不能在 React 中使用 D3。 正确的方法是始终将 DOM 操作留给 React,并使用 D3 作为计算属性的引擎。 例如,当使用 d3 力布局时,您可以使用 D3 计算 (x,y) 坐标,并将它们作为道具传递,以便 React 处理协调等。

在上面的例子中,我建议将<p .../>的渲染留给 React。 但是,我不知道您的最终目标是什么,因此除了将这个示例简单地转换为 React 之外,无法真正说出正确的方法是什么

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM