我已经开始在代码中引入一些React钩子,特别是useEffect
,我似乎无法找出我在做什么是否安全。本质上,我在挂钩内的DOM上运行动画,并且我想确保不会破坏任何DOM快照。
这是一个示例,我从完整的示例中进行了修改,以尝试简洁明了地说明正在发生的事情:
export function GrowingCircle(props) {
const root = useRef(null); // This is the root element we draw to
// The actual rendering is done whenever the data changes
useEffect(() => {
const radius = props.width / 2;
d3.select(root.current)
.transition()
.duration(1000)
.attr("r", radius);
}, [props.width]);
return (
<svg width={props.width} height="100%">
<circle ref={root} cx="0" cy="0" r="0" fill="red" />
</svg>
);
}
我关心的部分是.transition()
将在DOM上频繁运行更新1秒钟,我不确定这是否会影响react渲染?
一个后续问题(通常无法像本例一样控制动画渲染)。 circle
不在JSX内的以下内容是否会更改?
export function GrowingCircle(props) {
const root = useRef(null); // This is the root element we draw to
// The actual rendering is done whenever the data changes
useEffect(() => {
const radius = props.width / 2;
d3.select(root.current)
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("fill", "red")
.transition()
.duration(1000)
.attr("r", radius);
}, [props.width]);
return (
<svg ref={root} width={props.width} height="100%">
</svg>
);
}
答案 0 :(得分:1)
DOM元素可以被修改。 但是如果由于虚拟DOM与当前DOM(React具有的当前DOM)不匹配而使React需要重新渲染,则它可能会替换已修改的部分,以及对React所做的更改可能会丢失。
React修改了必要的部分,因此,如果React仅修改了元素的一部分或将其删除,则修改可能会保留。因此,据我了解,我们不能相信修改将继续存在。仅当我们确定在自定义修改后Component输出不会改变时。
我的建议是使用React来跟踪任何更改:
useState
和useEffect
来修改style
属性。答案 1 :(得分:0)
我一直在您的相同场景中,给您一个简短的答案,因为没有真正的D3-React实现,因此您需要绘制命令式与声明式渲染的边界。但是,在两个示例中,您实际上都没有违反任何规则。
在第二个示例中,您将the绳传递给D3进行完整渲染,而React simple保留对顶级svg元素的引用。在第一个示例中,您将渲染单个圆,并且仅使用D3管理其过渡。
但是,在第一个示例中,由于看起来您声明后从未更改DOM中的任何内容,因此React应该通常不会进行干预。这是第三个示例,实现了与您编写的内容类似的内容:
export function GrowingCircle(props) {
const root = useRef(null); // This is the root element we draw to
const [radius,setRadius] = useState(0); //initial radius value
useEffect(() => {
d3.select(root.current)
.transition()
.duration(1000)
.attr("r", props.width / 2)
.on("end", () => {setRadius(props.width / 2)}); //this is necessary
}, [props.width]);
return (
<svg width={props.width} height="100%">
<circle ref={root} cx="0" cy="0" r={radius} fill="red" />
</svg>
);
}
我本人也遇到了类似的问题,据我了解,在过渡期间d3直接作用于您想要的值,导致它不触发react的重新渲染机制。但是,一旦完成,我假设它直接尝试对半径值起作用,并且您的圆会捕捉回到其原始值0。因此,您只需添加.on('end')事件以更新其状态,就可以了!
我觉得这与react方法差不多,其中d3仅根据react状态选择渲染的元素。