我有一个 functional component
与 d3
附加 p
的函数到ref
在安装
我尝试使用 useState
更改附加段落的文本内容钩
点击按钮<button type="button" onClick={(e)=> setData("bar")}>change data</button>
触发重新渲染,而不是更改 p
的文本tag ,创建一个新版本的 d3 函数 --> 附加一个新的 p
阅读 How to rerender when refs change建议使用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')
: 选择所有 <p>
domRef.current
中的元素.data([data])
: 绑定(bind) <p>
元素到数据数组。绑定(bind)时,数组中的每个项目都有自己的<p>
. .join('p')
: join
将创建一个删除所有 <p>
的选择。没有关联的数据,并将更新那些有数据的。这将为您留下一个 <p>
, 因为 .data()
call before 数组中只有一个元素 .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 个段落:其中三个被绑定(bind)到 [1, 3, 5]
数组,其他三个绑定(bind)到[2, 4, 6]
关于javascript - 使用 d3 更新 dom ref 并使用react,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68099807/